Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changed value on AngularJS Service not triggering watch within directive

I'm having an issue getting a watch to work within a directive. I've put together a simple example here. http://plnkr.co/edit/A7zbrsh8gJhdpM30ZH2P

I have a service and two directives. One directive changes a property in the service, and another directive has a watch on that property. I expected the watch to fire when the property is changed but it doesn't.

I've seen a few other questions like this on the site, but the accepted solutions on them have not worked here. I've considered using $broadcast or trying to implement an observer, but it seems like this should work and I don't want to over complicate things if possible.

like image 594
Ian Muir Avatar asked Aug 01 '13 13:08

Ian Muir


People also ask

What is the use of $Watch in AngularJS?

$watch() function is used to watch the changes of variables in $scope object. Generally the $watch() function will create internally in Angularjs to handle variable changes in application.

What is Attrs in AngularJS?

scope is an AngularJS scope object. element is the jqLite-wrapped element that this directive matches. attrs is a hash object with key-value pairs of normalized attribute names and their corresponding attribute values. controller is the directive's required controller instance(s) or its own controller (if any).

What is the second argument in $Watch in AngularJS?

The $watch keep an eye on the variable and as the value of the variable changes the angular JS $what runs a function. This function takes two arguments one is the new value and another parameter is the old value.


2 Answers

Mark Rajcok' answer is incomplete. Even with angular.copy(), $watch listener will be called once and never again.

You need to $watch a function:

$scope.$watch(

  // This is the important part
  function() {
    return demoService.currentObject;
  },

  function(newValue, oldValue) {
    console.log('demoService.currentObject has been changed');
    // Do whatever you want with demoService.currenctObject
  },
  true
);

Here the plunker that works: http://plnkr.co/edit/0mav32?p=preview

Open your browser console to see that both the directive and the demoService2 are notified about demoService.currentObject changes.

And btw angular.copy() is not even needed in this example.

like image 132
tanguy_k Avatar answered Sep 29 '22 10:09

tanguy_k


Instead of

this.currentObject = newObject;

use

angular.copy(newObject, this.currentObject);

With the original code, the viewer directive is watching the original object, {}. When currentObject is set to newObject, the $watch is still looking for a change to the original object, not newObject.

angular.copy() modifies the original object, so the $watch sees that change.

like image 23
Mark Rajcok Avatar answered Sep 29 '22 11:09

Mark Rajcok