Discombobulous
Discombobulous

Reputation: 1184

Angular directive watch variable not triggering

First, here is the code:

app.controller('MainCtrl', function($scope) {
  $scope.test="Hello!";
  $scope.updateFlag = false;
  function updateFunc(){
    $scope.updateFlag = true;
  }
  $scope.updateFunc = updateFunc;

});



app.directive('dir1', function(){
  return {
    scope:{
      updateFunc:'='
    },
    link: function(scope,element,attr,ctrl){
      element.bind('click', scope.updateFunc);
    }
  }
});

app.directive('dir2', function(){
  return {
    template: '{{privateVal}}',
    scope:{
      updateFlag:'='
    },
    link: function(scope,element,attr,ctrl){
      scope.privateVal= "Not working!";
      scope.$watch(scope.updateFlag, function(newval, oldval){
        alert("watch triggered");
        if (newval===true){
          scope.privateVal = "Worked!!";
        }
      })
    }
  }
});

I have 2 directives, 1 with a 2-way binding to a global function, the other is watching a global variable that the global function is changing. However, somehow when the global function gets called, my watch function is not getting triggered. Any help is greatly appreciated.

Thanks,

Upvotes: 2

Views: 1460

Answers (2)

user1313891
user1313891

Reputation:

If you don't want to do this with this timeout option there are a couple other ways to tackle the problem, which i think have some advantages:

1.) Don't use isolate scope. Just called the method from the controller:

<button dir1 ng-click="updateFunc()">Click me!</button>

2.) Using isolate scope, use ng-click still, but like this: http://plnkr.co/edit/TrahxB.

You pass the function in as an attribute. Use a binding pattern of & and grab it from the scope object. You see I called it "update", then run it in the directive with ng-click=update(). This would also allow you to pass data from the directive to the controller in an object map, which could be useful as you build!
Here is a great tutorial to explain this.

Alternatively, if you want a isolate scoped directive, but don't need that function to be isolated you can put all the click logic in the DOM, then transclude it into the directive - use the strategy from #1. Transcluded dom elements are in the parent's controller scope - see this.

3.) Using isolate scope, you could use ng-click on the directive to call a function on the linking function of the directive to Emit an event to be watched on the controller.

Upvotes: 1

Jossef Harush Kadouri
Jossef Harush Kadouri

Reputation: 34257

because you are invoking native click event , the digest cycle does not get called. use $timeout to solve it:

app.directive('dir1', function($timeout){
  return {
    scope:{
      updateFunc:'='
    },
    link: function(scope,element,attr,ctrl){
      element.bind('click', function()
      {
        $timeout(scope.updateFunc)
      });
    }
  }
});

http://plnkr.co/edit/ReqExBvlPuRL5vp7WJ0y?p=preview

Upvotes: 3

Related Questions