Reputation: 4160
If I try to do a ng-repeat to databind some fields to an array for example using the $index
value then the input blurs automagically after 1 keystroke. Check the example to see what i mean.
(tested with angular stable 1.2.4 and latest: 1.2.5, and 1.1.1 from jsfiddle)
(fiddle: http://jsfiddle.net/Dj4n4/)
or the html bellow, same thing
<!doctype html>
<html ng-app>
<head>
<script src="js/angular.js"></script>
<script type="text/javascript">
function testController ($scope) {
$scope.data = {
a: 1,
b: '2222',
c: {
d: 3,
e: [1, 2, 3],
}
};
}
</script>
</head>
<body ng-controller="testController">
Works: <label><input type="text" ng-model="data.c.e[1]" /></label>
<br />
Blurs after one keystroke:
<label ng-repeat="no in data.c.e">
<input type="text" ng-model="data.c.e[$index]" />
</label>
<pre>{{data | json}}</pre>
</body>
</html>
Upvotes: 4
Views: 796
Reputation: 4160
I got a great answer from Michael Hard on the AngularJS Google Groups:
https://groups.google.com/forum/#!topic/angular/q1U-9Dj7leU
The solution is to use Angular >= 1.2.4 (the currently stable one works) and use track by
in the ng-repeat
, aka:
<label ng-repeat="no in data.c.e track by $index">
And the whole code:
<!doctype html>
<html ng-app>
<head>
<script src="js/angular.js"></script>
<script type="text/javascript">
function testController ($scope) {
$scope.data = {
a: 1,
b: '2222',
c: {
d: 3,
e: [1, 2, 3],
}
};
}
</script>
</head>
<body ng-controller="testController">
Works: <label><input type="text" ng-model="data.c.e[1]" /></label>
<br />
Blurs after one keystroke:
<label ng-repeat="no in data.c.e track by $index">
<input type="text" ng-model="data.c.e[$index]" />
</label>
<pre>{{data | json}}</pre>
</body>
</html>
Upvotes: 4
Reputation: 16571
It's because ng-repeat redraws every time the value changes. It works if you bind to integers in an object instead of an array:
f: [{no:1},{no:2},{no:3}]
// ...
<input type="text" ng-model="data.c.f[$index].no" />
You could watch a proxy object like that and use it to update the array.
$scope.$watch("data.c.f", function(){
$scope.data.c.e = [];
$scope.data.c.f.forEach(function(obj){
$scope.data.c.e.push(obj.no);
})
}, true)
Upvotes: 1