Binding inputs to an array of primitives using ngRepeat => uneditable inputs

眉间皱痕 提交于 2019-11-26 15:40:24

问题


Here is a demo to my problem.

$scope.myNumbers = [10, 20, 30];

<div ng-repeat="num in myNumbers">
    <input type="text" ng-model="num">
    <div>current scope: {{num}}</div>
</div>

Can anyone explain to me why are the inputs uneditable/readonly? If it's by design, what's the rationale behind?

UPDATE 2/20/2014

It looks like this is no longer an issue for v1.2.0+ Demo. But do keep in mind that although the user controls are now editable with the newer angularJS versions, it is the num property in the child scopes, not the parent scope, that get modified. In another words, modifying the values in the user controls does not affect the myNumbers array.


回答1:


Can anyone explain to me why are the inputs uneditable/readonly? If it's by design, what's the rationale behind?

It is by design, as of Angular 1.0.3. Artem has a very good explanation of how 1.0.3+ works when you "bind to each ng-repeat item directly" – i.e.,

<div ng-repeat="num in myNumbers">
  <input type="text" ng-model="num">

When your page initially renders, here's a picture of your scopes (I removed one of the array elements, so the picture would have fewer boxes):

(click to enlarge)

Dashed lines show prototypical scope inheritance.
Gray lines show child → parent relationships (i.e., what $parent references).
Brown lines show $$nextSibling.
Gray boxes are primitive values. Blue boxes are arrays. Purple are objects.

Note that the SO answer of mine that you referenced in a comment was written before 1.0.3 came out. Before 1.0.3, the num values in the ngRepeat child scopes would actually change when you typed into the text boxes. (These values would not be visible in the parent scope.) Since 1.0.3, ngRepeat now replaces the ngRepeat scope num values with the (unchanged) values from the parent/MainCtrl scope's myNumbers array during a digest cycle. This essentially makes the inputs uneditable.

The fix is to use an array of objects in your MainCtrl:

$scope.myNumbers = [ {value: 10}, {value: 20} ];

and then bind to the value property of the object in the ngRepeat:

<div ng-repeat="num in myNumbers">
  <input type="text" ng-model="num.value">
  <div>current scope: {{num.value}}</div>



回答2:


This problem is now addressed by more recent versions of AngularJS with the track by feature allowing repeaters over primitives:

<div ng-repeat="num in myNumbers track by $index">
  <input type="text" ng-model="myNumbers[$index]">
</div>

The page will not get repainted after each keystroke, which solves the problem of the lost focus. The official AngularJS doc is quite vague and confusing about this.




回答3:


Seems that Angular is not able to write to model defined that way. Use reference to initial $scope attribute to let it bind value right way:

<div ng-repeat="num in myNumbers">
  <input type="text" ng-model="myNumbers[$index]">
</div>



回答4:


ngRepeat uses a reference to the source array. Since integer (Number in js) is a value type, not a reference type, therefore cannot be passed by reference in javascript. The change will not be propagated.

Here is a demonstration:

   var x = 10;
   var ox = {value:10};

   var y = x;
   var oy = ox;

   y = 15
   oy.value = 15;

What would be the values of x and ox?

>> x = 10;
>> y = 15;
>> ox = {value:15};
>> oy = {value:15};

All javascript objects are passed by reference and all primitives are passed by value ["string", "number", etc].

Working plunker http://plnkr.co/edit/7uG2IvAdC2sAEHbdHG58




回答5:


I had a similar issue (and also required 'add' and 'remove' functionality), and solved the problem like so:

$scope.topics = [''];
$scope.removeTopic = function(i) {
   $scope.topics.splice(i, 1); 
}

<div ng-repeat="s in topics track by $index">
    <input ng-model="$parent.topics[$index]" type="text">
    <a ng-click="removeTopic($index)">Remove</a>
</div>

<a ng-click="topics.push('new topic')">Add</a>


来源:https://stackoverflow.com/questions/15488342/binding-inputs-to-an-array-of-primitives-using-ngrepeat-uneditable-inputs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!