Michal Foksa
Michal Foksa

Reputation: 12034

Ionic, AngularJs: Directive attribute $watch stops working after view is rendered

I want to create an attribute directive for ionItem and I want it to watch its own value:

<ion-item ng-repeat="item in items" my-dir="{{data.watchedValue}}">….</ion-item>

I have an issue with creating correct watch statement in the directive. The watch is executed only once during initial view rendering. After that it is not invoked when data.watchedValue is changed.

Specific of the directive is that it is child of ionItem directive.

I have tried multiple approaches (see comments in my-dir source), but none of them works.

Directive:

.directive('myDir', function() {
  return {
    restrict: 'A',
    require:  '^ionItem',
    link: function(scope, element, attr, itemCtrl) {
      console.log('my-dir initial value: ' + attr.myDir);

      if (angular.isDefined(attr.myDir)) {
        // scope.$watch("(" + attr.myDir + " === \"true\")", function(value) {
        // scope.$watch('!!(' + attr.myDir + ')', function(value) {
        scope.$watch(attr.myDir, function(value) {
          console.log('my-dir watch new value:  ' + value);
        });
      }

    } // link
  }; // return
}) // directive

Simplified directive usage:

<button class="button" ng-click="data.watchedValue = !data.watchedValue">
  Change Value
</button>

<ion-content>
  <ion-list>
    <ion-item ng-repeat="item in items" my-dir="{{data.watchedValue}}">
      Item {{ item.id }}. Watched property: {{ data.watchedValue }}
    </ion-item>
  </ion-list>
</ion-content>

Code Pen with full example. Press Change Value button to … change value.

Watch the console for any logs after initial display.

Upvotes: 0

Views: 85

Answers (1)

Pankaj Parkar
Pankaj Parkar

Reputation: 136184

You should be just passing scope variable name to directive attribute

<ion-item ng-repeat="item in items" my-dir="data.watchedValue">
  Item {{ item.id }}. Watched property: {{ data.watchedValue }}
</ion-item>

OR

you could use attrs.$observe instead of $scope.$watch, which will basically keep an watch on {{}} interpolated value specified on attribute.

If data.watchedValue has object then I'd highly recommend to go for 1st approach.

Upvotes: 2

Related Questions