Reputation: 13790
I have this code
http://plnkr.co/edit/aycnNVoD96UMbsC7rFmg?p=preview
<div data-ng-app="" data-ng-init="names=['One']">
<input type="text" ng-model="names[0]">
<p>Looping with ng-repeat:</p>
<ul>
<li data-ng-repeat="name in names">
<input type="text" ng-model="name"> {{ name }}
</li>
</ul>
</div>
When i change value of name[0] in the first input box it changes values of the second input box. But when i change value of name[0] in the second input box it does not change value of the first input box. Why?
Upvotes: 1
Views: 271
Reputation: 17492
This is due to ng-repeat
creating a child scope, so the reference to name inside the ng-repeat
is different to that original one in the names array, see here:
New AngularJS developers often do not realize that ng-repeat, ng-switch, ng-view and ng-include all create new child scopes, so the problem often shows up when these directives are involved. (See this example for a quick illustration of the problem.)
Regarding as to why this happens, when you bind the input to name in names inside the ng-repeat
, you are creating a new property on the new child scope created by the ng-repeat
called name
, and thus the ng-model
of the textbox created by the ng-repeat is referencing a different name to that of the actual 0th element of the names array. As others have pointed out, if you use names[$index]
you are implicitly referencing the 0th element of the names
array, thus NOT creating a new name property on the child scope created by the ng-repeat
. An angular best practice is not to have ng-models bound to primitives, rather objects, Sandy has mentioned in his answer if you bind to an object you will overcome this, and the 2 other posters have answered this by using $index
to refer to the 0th element of the names array. This is one of the nucances of scope inheritance in angular.
A couple more handy links:
Upvotes: 1
Reputation: 1868
You need to provide
$index
in your ng-model.
<li data-ng-repeat="name in names">
<input type="text" ng-model="names[$index]"> {{ name }}
</li>
You are binding ng-model="names[0]"
. So it means that you are binding value on first index of names
array.
So when we write ng-model="names[$index]"
in ng-repeat
it means that all values will be bound accordingly into array. $index
is an iterator offset of the repeated element.
names[0] = 'One'
names[1] = 'Two'
and so on!
Upvotes: 1
Reputation: 11687
Just wanted to give my bit on this. Somewhat related to your problem as I see.
<body>
<div data-ng-app="" data-ng-init="names=[{value:'One'}, {value:'Two'}]">
<p>Looping with ng-repeat:</p>
<ul>
<li data-ng-repeat="name in names">
<input type="text" ng-model="name.value"> {{ name }}
</li>
</ul>
</div>
</body>
Instead of binding the array item directly to the control, I would prefer to create an object of the array and then bind value of each item. This way we can avoid reference problems.
A working prototype jsfiddle
Hope it helps.
Upvotes: 1
Reputation: 186
It works if you bind your second input to : names[$index]
<input type="text" ng-model="names[$index]"> {{ name }}
Upvotes: 2