How do I access ng-model values inside my directive template?


I have a directive with a template that looks like

<!-- selectList.tpl.html -->
<div ng-if="selectList">
  <p>Id: {{$id}}</p>
  <p>Current list item {{currentItem}}</p>
  <select ng-model="currentItem"
    ng-options="item as item.value group by for item in selectList">
    <option value="">All</option>

I'm trying to access the currentItem value from inside my directive link function to create a watch function ie,

app.directive('selectList', [
  function (
  ) {
    "use strict";

    var getList = function() {
      // ...

    return {
      restrict: 'E',
      templateUrl: 'selectList.tpl.html',
      link: function(scope, element, attrs) {
        scope.selectList = getList();
        scope.currentItem = "";

        console.log("scope id:", scope.$id);

        scope.$watch('currentItem', function(item) {
          $timeout(function() {
            console.log("currentItem is", item);
            angular.element("#console").append("<p>Updated item: " + item + "</p>");

However, a child scope is created under the linkscope which stores changes to the values of the select box. How do I access the select box changes inside my directive link code?

I'm using Angular 1.1.5.

Here is a plunker of the problem (have updated code in the q to reflect the plunker):

Problem courtesy of: zlog


The ng-if is creating another scope. So when you update the value in the child scope it is not updating the parent scope.

See updated plunker:

If you need to keep the ng-if you will need to call a function defined in the parent scope from the child scope.

Solution courtesy of: rgaskill


You can declare a scope in your directive and set up two-way binding with an attribute. For example:

<my-directive attr="myVal">

myApp.directive('myDirective', function() {
    return {
        restrict: 'E',
        scope: {
            attr: '=',
        template: '<select ng-model="attr"> ... </select>',
        replace: true

You should theoretically be able to use ng-model directly, but I had trouble with it. If the attribute name and the variable name declared in scope are the same, you can use the scope the way I wrote in the example. Otherwise, you will have to be more specific.

Discussion courtesy of: C1pher

This recipe can be found in it's original form on Stack Over Flow.