Saurabh Tiwari Saurabh Tiwari - 25 days ago 8x
AngularJS Question

ng-change function called multiple times from input inside ng-repeat

Well, I have a issue here. I have an ng-repeat inside which an input with ng-change() is present. This is a part of directive template and double way binded to a parent object. If I type in something in input box, everything works fine and parent object is updated. However, when I have to replace the parent object from directive's controller, I face an issue.

The issue is that, once parent object gets replaced, the view is bound with new (replaced) values. Also at that time the same function (as in ng-change()) is triggered manually for some calculation.

However, I noticed that the same function is again getting called again (no idea how). The important thing is the ng-model of input is undefined, when they are automatically called. As a result, finally the parent object contains value undefined.

I am still confused, why the ng-change is getting called, after the controller method calls. Is it have to do something with child scopes that ng-repeat creates.

I have already used track by $index.
and I have binded models to parentObj.something.something[$index]

Any help on above is appreciated...

I have

module.directive('myDirective', function () {
return {
scope: {
target: '=',
controller: 'DemoController',
templateUrl: 'app/demo/html/demo.html'

Main template:

<li ng-repeat="l in group_Main.mains"
<li ng-repeat="target in l.description.Value track by $index"
<li ng-repeat="(key, groups) in track by $index">
<div layout="row" layout-wrap myDirective target="group"></div>

app/demo/html/demo.html::Directive's template

<div class="table_FY_height" flex ng-repeat="m in months track by $index">
<input ng-change="changeIt(target.targets.years[1][$index], target, year,parent, $index)"" ng-if="$index>currentMonth" ng-model="target.targets.years[1][$index]"/>

In directive's controller:

module.controller('DemoController', function($scope, $rootScope){

From directive's controller, I am trying to call a API and update target data as:

for(var i=0; i<12; i++){
target.targets.years[1][i] = APIResponse.targets.years[1][i]
}}, function(error){
//error handling here}

Doing this calls the dirrective and updates the view on screen with new values from APIResponse. Since, the directive view is controlled using ng-show, the new values remain intact in the view. This function is called once in controller per directive call with first argument as -1. But after that it again runs with first value as 'undefined'. With undefined, it runs as many times as the directive is compiled. Consequently the target.targets.years[1][$index] becomes undefined.

Any ideas whats going wrong? I have been scratching my head over it for hours.


I dug deep into the issue and found that in my case I had a directive placed on input tag, which was parsing the model after it is bound. (It was basically used for some kind of rounding off. So I removed that logic and started passing rounded figures from server. The issue ceased to appear). So my conclusion was that the second ng-change is fired because the model is again changed by the directive. Anyone facing such issues should look for any other kind of change to the model after initial binding.

Posting this as the answer, as this was the solution in my case.