Swapnil Jain
Swapnil Jain

Reputation: 1516

Watch is not working inside a custom attribute directive used inside another custom element directive

I have two directives which implement independent functionality. I am trying to use the attribute directive inside an element directive, but watch is not working on the attribute directive. Here's the jsfiddle link : http://jsfiddle.net/hsyR5/8/

I want the isLoaded directive watch to be triggered whenever is-loaded attribute value is changed.

Html:

<div ng-app="myapp">    
    <div ng-controller="ReportCtrl">
        <mydir is-loaded="false" id="change" expand-me="isExpanded" ng-transclude>
            <button ng-click="expandIt()"> Expand</button>
        </mydir>
    </div>

Javascript code:

var myApp = angular.module('myapp', [])
myApp.directive('mydir', function () {   
    return {
        restrict: 'E',
        scope : {
            expandMe:'='
        },
        replace: true,
        transclude: true,
        template : "<div></div>",
        link: function (scope, element, attrs) {
            scope.$watch('expandMe', function (){
                //load the data
                console.log('inside mydir directive');
                element[0].attributes['is-loaded'].nodeValue = ''+scope.expandMe;
            });
        }
    };
});

myApp.directive('isLoaded', function () {
    return {
        restrict : 'A',
        link: function (scope, element, attrs) {
            scope.$watch(attrs.isLoaded, function (){
                console.log('isLoaded Changed');
            });
        }
    };
});

myApp.controller('ReportCtrl', function($scope){
 $scope.isExpanded = false;
  $scope.expandIt = function(){
      $scope.isExpanded = !$scope.isExpanded;
  }
})

Upvotes: 0

Views: 2450

Answers (1)

charlietfl
charlietfl

Reputation: 171679

Using scope.$watch if you pass a string as first argument, it needs to match a scope property.

Your attempt would be similar to writing:

scope.$watch("false", function (){
     ....
});

But scope.false is undefined.

Since you aren't watching a scope properrty you can use a function that returns a variable to watch as first argument

scope.$watch(function (){
     return attrs.isLoaded;/* define what to watch*/
}, function(newVal,oldVal
      if(newVal !=oldVal){
           console.log('isLoaded Changed');
      }
});

You can also use attrs.$observe similar to using $watch on scope

In the first directive element[0].attributes is unnecessary since the attributes are already available as argument of link. You can change an attribute using:

attrs.isLoaded = '' + scope.expandMe;

DEMO

Upvotes: 4

Related Questions