Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular Directive's template binding doesn't update

I have a directive set up here http://jsfiddle.net/screenm0nkey/8Cw4z/3 which has two bindings to the same scope property, but for some reason the binding in the directive's template property doesn't update when the model changes (after typing in the input).

<test>
    <h3>Inner {{count}}</h3>
    <input type="text" ng-model="count">
</test>

var App = angular.module('App', []);
App.directive('test', function() {
    return {
      restrict: 'E',
      replace: true,
      transclude: true,
      template: "<h1>Outer{{count}} <div ng-transclude></div></h1>",
      controller: function ($scope) {
        $scope.count = 1;
      }
    };
  });

But if I move the input position in the markup it works and both bindings update.

<input type="text" ng-model="count">
<test>
     <h3>Inner {{count}}</h3>
</test>

http://jsfiddle.net/screenm0nkey/dCvZk/3

Can anyone explain why the position of the input containing the binding, would have an affect the bindings. I assumed that during the digest loop the watchers for both binding would be updated regardless of the position of the markup.

Many thanks

like image 296
screenm0nkey Avatar asked Jan 03 '14 14:01

screenm0nkey


1 Answers

To me, this seems purely to be a scope issue. Lets take a look at the markup that is generated by both:

Not working:

<body ng-app="App" class="ng-scope">
  <h1 class="ng-binding">Outer1 <div ng-transclude="">
    <h3 class="ng-scope ng-binding">Inner 1</h3>
    <input type="text" ng-model="count" class="ng-scope ng-pristine ng-valid">
    </div>
  </h1>
</body>

Working:

<body ng-app="App" class="ng-scope">
  <input type="text" ng-model="count" class="ng-valid ng-dirty">
  <h1 class="ng-binding">Outer <div ng-transclude="">
    <h3 class="ng-scope ng-binding">Inner </h3>
    </div>
  </h1>
</body>

The ng-scope class is a useful marker for where Angular is declaring a new scope.

You can see by the markup that the in the working example both the count properties are enclosed in the scope that is attached to body. So, in this case, the directive scope is a child of the body scope (and therefore has access to it).

However, In the example that is not working, the Outer1 property is sitting outside of the scope that the input is in.

The Angular Scope documentation covers this well. The scopes are arranged in a hierarchy with child scopes having access to parent scopes (but not the other way around):

The application can have multiple scopes, because some directives create new child scopes (refer to directive documentation to see which directives create new scopes). When new scopes are created, they are added as children of their parent scope. This creates a tree structure which parallels the DOM where they're attached

angular scope heirarchy

like image 71
Davin Tryon Avatar answered Oct 10 '22 23:10

Davin Tryon