angular trigger changes with $watch vs ng-change, ng-checked, etc
Asked Answered
L

4

49

Currently we could monitor data changes with several ways. We could trigger model changes with $watch and we could add directives to elements and bind some actions to it.

It's a little bit confusing in many cases, so I'm curious, which is pro and cons of each variant and when should we use $watch binding, and when directives like ng-change?

Lorenzen answered 25/9, 2013 at 14:9 Comment(0)
D
61

Both $watch and ngChange have totally different usages:

Lets say you have a model defined on a scope:

$scope.myModel = [
    {
        "foo":"bar"
    }
];

Now if you want to do something whenever any changes happen to myModel you would use $watch:

$scope.$watch("myModel", function(newValue, oldValue){
    // do something
});

ngChange is a directive that would evaluate given expression when user changes the input:

<select ng-model="selectedOption" ng-options="option for option in options" 
ng-change="myModel=selectedOption"></select>

In short, you would normally bind ngChange to some HTML element. While $watch is for the models.

Durst answered 25/9, 2013 at 14:21 Comment(3)
but $watch("input", inputChanged, true) will also working and will triggering when you change your input value.Lorenzen
The difference is that ng-change does not evaluate the expression when the value change is coming from the model while $watch specifically listens to the model updates.Durst
So you mean if bind data to model, then add watch listener to that model, and then will change model inside listener - then it will evaluate watch listener once again?Lorenzen
C
16

Code of ngChange directive:

var ngChangeDirective = valueFn({
  require: 'ngModel',
  link: function(scope, element, attr, ctrl) {
    ctrl.$viewChangeListeners.push(function() {
      scope.$eval(attr.ngChange);
    });
  }
});

Guess what, ngChange requires a controller from ngModel and executes the bound expression when the view is changed.

So it's like a helper that save you from doing tedious tasks like [$watch 'model' then do stuff].

On performance perspective, you have one less $watch expression to worry about.

Cason answered 25/9, 2013 at 15:36 Comment(2)
Is that last statement true? Is $viewChangeListeners not like a $watch itself?Chastain
yes it is true, you can refer to this article for more detailed explanation :) accelebrate.com/blog/…Cason
F
8

Directives like ng-change are used for data-binding to DOM. $watch is used in your JS code to listen for changes.

When you need to have the DOM be affected by a change in your scope, or need to have a change in DOM (eg. field selection) affect the scope, you would use a directive.

If you need to trigger JavaScript actions from a change in scope, for example an ajax request, then you would use $watch in your controller (or service) to listen for the change.

Finnic answered 25/9, 2013 at 14:14 Comment(2)
but if you bind element to model, like input. then when you change input value - it's automatically change the model field value. And then $watch listener will be triggered and you could implement any logic you want without directing dom manipulation, only interacting with model.Lorenzen
Yes that's exactly what directives are for. Directives deal with DOM, and your JS code in controllers/services can deal with other things.Finnic
M
2

If you want two-way data binding, then use ng-model. This pushes changes from model to view and from view to model -- two ways. However, if you just want one-way data binding from view to model, then use ng-change. If you want simple one way data binding from model to view, you can use an expression {{ like_this }}. But if you want a lot more control over how the model is rendered in the view, or if you want to bind the model to something other than the view, then use a $watch.

Matisse answered 9/6, 2016 at 15:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.