ng-change or $watch?

1,579 views
Skip to first unread message

Mauro Sanna

unread,
Apr 30, 2013, 12:50:37 PM4/30/13
to ang...@googlegroups.com
I'm using ng-change on a select:

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

I want try $watch but the code does not work.

$scope.$watch('selected', function (selected) {
    $scope.selectedList.push(selected);
  });

Amir H. Hajizamani

unread,
Apr 30, 2013, 2:03:54 PM4/30/13
to ang...@googlegroups.com
Hi Mauro,

You've been caught out by Angular's scope inheritance hierarchy: http://docs.angularjs.org/guide/scope#scopehierarchies

Within each iteration of the ng-repeat a *new* scope is created which inherits from its parent, in this case MainCtrl. These new scopes inherit the properties and methods of your MainCtrl which is why you can call 'addSelected' in your event handler. However, when you refer to 'selected' in your ng-model, when the value changes it is assigned to a property directly on these child scopes, not on MainCtrl. So in your plunker 'addSelected(selected)' works because the child scope knows about the method from its parent scope, and can pass in the 'selected' property directly from itself.

When you put your $watch code on MainCtrl's scope, it is looking for a 'selected' model on MainCtrl which doesn't exist, and it knows nothing about those child scopes that ng-repeat created. You need to make sure that those child scopes refer to exactly one model that you can access on MainCtrl, and you do this by referring to something inside an Object. So finally (!), here is your code modified to use $watch: http://plnkr.co/edit/TfVU4CYjzfWN2UQZmwld 

The rule of thumb to avoid this problem is 'if you use ng-model there has to be a dot somewhere'.

Watching this short video (and the two before it in the series) might help clarify all this: The Dot http://www.egghead.io/video/DTx23w4z6Kc
For more depth, watch this: AngularJS Best Practices http://www.youtube.com/watch?v=ZhfUv0spHCY

Hope that helps explain things.

Amir

Mauro

unread,
Apr 30, 2013, 2:13:11 PM4/30/13
to ang...@googlegroups.com
What a great and exhaustive answer, thank so much, I'm new to angular and English is not my mother language so sometimes I have difficulty to understand the docs.
Your answer is very exhaustive.
Thank you very much.


--
You received this message because you are subscribed to a topic in the Google Groups "AngularJS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/angular/0c8macTk0hY/unsubscribe?hl=en-US.
To unsubscribe from this group and all its topics, send an email to angular+u...@googlegroups.com.
To post to this group, send email to ang...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular?hl=en-US.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Amir H. Hajizamani

unread,
Apr 30, 2013, 2:18:52 PM4/30/13
to ang...@googlegroups.com
Glad it helped!
The docs are not great in some places, but those egghead.io videos are great, highly recommend you watch them if you have a couple of hours to spare.

Edgar Monge

unread,
Dec 4, 2014, 6:20:03 PM12/4/14
to ang...@googlegroups.com
hi Mauro, looking at you example if you use tab and arrow down, it doen't work. any ideas why?  ex. if you tab and using the down arrow you select a, the object update to a, then select b the object does not update, then select c and the object updated to a,c

any ideas why this doesn't work?
 I have the same issue in my applications

melanie johnson

unread,
Jul 2, 2015, 2:56:53 PM7/2/15
to ang...@googlegroups.com
I assume you're using FF?  See this StackOverflow post for discussion of this behavior (it likely has to do with when the browser fires the onchange event) and for a sample directive to fix it.  

m
Message has been deleted

melanie johnson

unread,
Jul 2, 2015, 3:41:10 PM7/2/15
to ang...@googlegroups.com
I found this thread looking for thoughts on the following: when is it better to use ng-change versus a $watch on the model?  

Right now I'm looking at code in which we $watch multiple properties within an object and call the same function when any of them changes (I assume this is more efficient than watching the whole object?).  Here's some pseudocode (I don't think a plnkr is necessary here). 

HTML:

<label><input type="checkbox" ng-model="someOptions.checkboxChoice"> whatever</label>
<select ng-model="someOptions.dropdownChoice" ng-options="key for (key, value) in dropdownChoices" />

In the directive's link function:

var updateSettings = function () {
   // do some stuff that involves the whole someOptions object
};

scope.dropdownChoices = { 'optionName1': 0, 'optionName2': 1 };

scope.someOptions = {
   checkboxChoice: true,
   dropdownChoice: 0
};

scope.$watch('someOptions.checkboxChoice', updateSettings);
scope.$watch('someOptions.dropdownChoice', updateSettings); 

...What if I just added ng-change="updateSettings()" to the input elements instead of having all the watches?  (In the actual code, we have more than one checkbox and dropdown, plus some radio buttons.)  It seems to work fine (the scope is updated by the time the call is made).  Is there a performance benefit to either?

Thanks,
M

Sander Elias

unread,
Jul 2, 2015, 10:40:33 PM7/2/15
to ang...@googlegroups.com
Hi Melanie,

Yes, there is a huge performance gain if you use ng-change. Those are only run, when there is a change in your relevant ngModelController. Your watches will get fired on every digest loop. 

Regards
Sander
Reply all
Reply to author
Forward
0 new messages