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

46,734

Solution 1

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.

Solution 2

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.

Solution 3

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.

Solution 4

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.

Share:
46,734
Ph0en1x
Author by

Ph0en1x

Founder and architect in Centaurea (http://centaurea.io) - awesome software development and consulting company that specialises in construction of high-load, scalable, distributed and Big Data processing systems.

Updated on July 09, 2022

Comments

  • Ph0en1x
    Ph0en1x almost 2 years

    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?

  • Ph0en1x
    Ph0en1x almost 11 years
    but $watch("input", inputChanged, true) will also working and will triggering when you change your input value.
  • Ph0en1x
    Ph0en1x almost 11 years
    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.
  • AlwaysALearner
    AlwaysALearner almost 11 years
    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.
  • Ph0en1x
    Ph0en1x almost 11 years
    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?
  • Jani Hartikainen
    Jani Hartikainen almost 11 years
    Yes that's exactly what directives are for. Directives deal with DOM, and your JS code in controllers/services can deal with other things.
  • morgs32
    morgs32 almost 8 years
    Is that last statement true? Is $viewChangeListeners not like a $watch itself?
  • 6220119
    6220119 over 7 years
    yes it is true, you can refer to this article for more detailed explanation :) accelebrate.com/blog/…