Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular JS: get ng-model on ng-change

I have the following HTML

<select ng-model="country" ng-options="c.name for c in countries" ng-change="filterByCountry"></select>

That is beeing fed by the following object with a list of countries

$scope.countries = [{name:Afeganistão, country:AF}, {name:África do Sul, country:ZA}, name:Albânia, country:AL}, {name:Alemanha, country:DE}, {name:Andorra, country:AD} ...];

When I change my dropdown value I was expecting my model ($scope.country) to be updated, inside filterByCountry function, but it isn't. What am I missing here?

like image 928
Joao Almeida Avatar asked Mar 26 '14 18:03

Joao Almeida


People also ask

What is NG-model and Ng-change?

Ng-change is a directive in AngularJS which is meant for performing operations when a component value or event is changed. In other words, ng-change directive tells AngularJS what to do when the value of an HTML element changes. An ng-model directive is required by the ng-change directive.

What is $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 ngInit?

The ngInit directive allows you to evaluate an expression in the current scope. This directive can be abused to add unnecessary amounts of logic into your templates. There are only a few appropriate uses of ngInit : aliasing special properties of ngRepeat , as seen in the demo below.

What is the difference between ng-model and data NG model?

There is no difference between ng-model and data-ng-model if you see in terms of AngularJs. Actually, 'data' used as prefix to validate HTML5 validation. So, it is good practice to use data-ng-model , however, you can use ng-model as well. There is no problem in that also.


2 Answers

The ng-change handler is fired before the ng-model is actually updated. If you want filterByCountry to be fired every time $scope.country changes (rather than just when the dropdown changes), you should use the following instead:

$scope.$watch('country', filterByCountry);

I always find it more useful to react to changes in my $scope rather than DOM events when possible.

like image 102
Justin Niessner Avatar answered Oct 07 '22 18:10

Justin Niessner


Just for anyone else coming here, ng-change is actually called after the model value has been set.

Why?
Let's see when is it called. From the angular source code, ng-change is just an attribute directive with this directive definition object (DDO).

{
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, element, attr, ctrl) {
      ctrl.$viewChangeListeners.push(function() {
        scope.$eval(attr.ngChange);
      });
    }
}

From this we see that the ng-change directive is very simple. All that ng-change='<expr>' does is add a function to the end of $viewChangeListeners that evaluates <expr> via $scope.$eval.

OK ... so when are the ViewChangeListeners called?

Well, if we look at the documentation for ngModel.NgModelController:

the new value will be applied to $modelValue and then the expression specified in the ng-model attribute. Lastly, all the registered change listeners, in the $viewChangeListeners list, are called.

So the viewChangeListener for the ngChange will be invoked after the value is applied to $modelValue. Hence the callback will be invoked after the model as been set.

Also note that this behavior is the same in all versions of angular. The definition for ng-change hasn't changed since v1.2.

like image 26
James Lawson Avatar answered Oct 07 '22 18:10

James Lawson