0

From the directive, I want to track changes to a controller variable using $watch. I have created this jsfiddle. (https://jsfiddle.net/hqz1seqw/7/)

When the page loads, the controller and both directives $watch function gets called but when I change the radio buttons, only the controllers and dir-two $watch function gets called. Why isnt dir-ones $watch function being called?

I want both the directives $watch to fire however, I can only get one of them to (i.e. dir-two). Not sure what I need to change. Does it have something to do with isolated scope? Is there a better way of doing this?

AngularJS Code:

var mod = angular.module("myApp", []);
//Controller
mod.controller("myCtrl", function($scope){
   $scope.tempformat = "C";
    $scope.one="25 - dir-one";
            $scope.$watch('tempformat', function(nv){
            alert("nv from controller");
            });  
    $scope.two="35 - dir-two";
});
//dir-one directive
mod.directive("dirOne", function(){
    return{
        restrict: 'E',
        template: "<p>{{info}}</p>",
        scope: {info: '='
        },
        link: function (scope, element, attr) {
            scope.$watch('tempformat', function(nv){
            alert("nv from directive-one");
              if(scope.tempformat === "C"){
                  element.find("p").append("C");
              }
              else if(scope.tempformat === "F"){
                  element.find("p").append("F");
              }                
            });    
        }        
    }});
//dir-two directive
mod.directive("dirTwo", function($window){
    return{
        restrict: "EA",
        template: "<p></p>",
        link: function (scope, element, attr) {
          scope.$watch('tempformat', function(nv){
            alert("nv from directive-two");  
              if(scope.tempformat === "C"){
                  element.find("p").append("C");
              }
              else if(scope.tempformat === "F"){
                  element.find("p").append("F");
              }
            });          
    }
    }    
});

HTML Code:

<div ng-app="myApp" ng-controller="myCtrl">
<h2>Temperature</h2>
    <input type="radio" ng-model="tempformat" value="C"/> Celcius
    <input type="radio" ng-model="tempformat" value="F"/> Farenheit
    <dir-one info="one"></dir-one>
    <dir-two info="two"></dir-two>
</div>

1 Answer 1

1

Does it have something to do with isolated scope?

The problem is the fact that dir-one separates its scope from the parent. There are some alternatives that can be done in this situation such as:

scope.$watch('$parent.tempformat', function(nv){ //...

which will look to the parent for the specified content.

Another alternative is to bind to the directive itself:

scope: {
        info: '=', 
        tempformat: '='
    },

and then in the html:

<dir-one info="one" tempformat="tempformat"></dir-one>

see: the documentation for more information. Particularly the Isolating the Scope of a Directive area.

Is there a better way of doing this?

In general isolate scopes help construct reusable components (as noted in the documentation) so if this is something that is being attempted (from the content noted in the answer) then I would support something along the lines of the second option where you can specify that watch content on the directive itself and consider that the "better" way of doing this.

From my experience, and this is solely my own preference, I would bind it to the directive since I usually isolate my scope(s) for a reason.

Sign up to request clarification or add additional context in comments.

1 Comment

I used the second alternative. Reading the documentation helped a lot too.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.