Difficulty with ng-model, ng-repeat, and inputs
This seems to be a binding issue.
The advice is don't bind to primitives.
Your ngRepeat
is iterating over strings inside a collection, when it should be iterating over objects. To fix your problem
<body ng-init="models = [{name:'Sam'},{name:'Harry'},{name:'Sally'}]"> <h1>Fun with Fields and ngModel</h1> <p>names: {{models}}</p> <h3>Binding to each element directly:</h3> <div ng-repeat="model in models"> Value: {{model.name}} <input ng-model="model.name"> </div>
jsfiddle: http://jsfiddle.net/jaimem/rnw3u/5/
Using Angular latest version (1.2.1) and track by $index
. This issue is fixed
<div ng-repeat="(i, name) in names track by $index"> Value: {{name}} <input ng-model="names[i]"> </div>
You get into a difficult situation when it is necessary to understand how scopes, ngRepeat and ngModel with NgModelController work. Also try to use 1.0.3 version. Your example will work a little differently.
You can simply use solution provided by jm-
But if you want to deal with the situation more deeply, you have to understand:
- how AngularJS works;
- scopes have a hierarchical structure;
- ngRepeat creates new scope for every element;
- ngRepeat build cache of items with additional information (hashKey); on each watch call for every new item (that is not in the cache) ngRepeat constructs new scope, DOM element, etc. More detailed description.
- from 1.0.3 ngModelController rerenders inputs with actual model values.
How your example "Binding to each element directly" works for AngularJS 1.0.3:
- you enter letter
'f'
into input; ngModelController
changes model for item scope (names array is not changed) =>name == 'Samf'
,names == ['Sam', 'Harry', 'Sally']
;$digest
loop is started;ngRepeat
replaces model value from item scope ('Samf'
) by value from unchanged names array ('Sam'
);ngModelController
rerenders input with actual model value ('Sam'
).
How your example "Indexing into the array" works:
- you enter letter
'f'
into input; ngModelController
changes item in namesarray
=> `names == ['Samf', 'Harry', 'Sally'];- $digest loop is started;
ngRepeat
can't find'Samf'
in cache;ngRepeat
creates new scope, adds new div element with new input (that is why the input field loses focus - old div with old input is replaced by new div with new input);- new values for new DOM elements are rendered.
Also, you can try to use AngularJS Batarang and see how changes $id of the scope of div with input in which you enter.