1

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?

Andrzej Rehmann
  • 12,360
  • 7
  • 39
  • 38

4 Answers4

2

It works if you bind your second input to : names[$index]

<input type="text" ng-model="names[$index]"> {{ name }}

Mualki
  • 186
  • 6
1

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!

Shreejibawa
  • 1,860
  • 1
  • 25
  • 35
1

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:

Here and here.

Community
  • 1
  • 1
Mohammad Sepahvand
  • 17,364
  • 22
  • 81
  • 122
1

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.

Sandy
  • 11,332
  • 27
  • 76
  • 122
  • Per your request, I've added additional detauils to my answer addressing why the solution proposed by you and the other 2 posters relate to my answer. – Mohammad Sepahvand Feb 26 '15 at 11:55
  • Oops...failed to express myself. I meant your approach was better on not discussing about fix but rather giving explanation. Inspired by your answer, I gave explanation :D – Sandy Feb 26 '15 at 11:58