使用ngRepeat =>不可编辑的输入将输入绑定到基元数组

tam*_*are 41 angularjs angularjs-scope angularjs-ng-repeat

这是我的问题的演示.

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

<div ng-repeat="num in myNumbers">
    <input type="text" ng-model="num">
    <div>current scope: {{num}}</div>
</div>
Run Code Online (Sandbox Code Playgroud)

任何人都可以向我解释为什么输入不可编辑/只读?如果按照设计,背后的理由是什么?

更新2/20/2014

看起来这不再是v1.2.0 + Demo的问题.但请记住,虽然用户控件现在可以使用较新的angularJS版本进行编辑,但它是子范围中num属性,而不是父范围,可以进行修改.换句话说,修改用户控件中的值不会影响数组.myNumbers

Mar*_*cok 67

任何人都可以向我解释为什么输入不可编辑/只读?如果按照设计,背后的理由是什么?

它是设计的,从Angular 1.0.3开始.当你"直接绑定到每个ng-repeat项目"时,Artem 对1.0.3+如何工作有很好的解释 - 即,

<div ng-repeat="num in myNumbers">
  <input type="text" ng-model="num">
Run Code Online (Sandbox Code Playgroud)

当您的页面最初呈现时,这里是您的范围的图片(我删除了一个数组元素,因此图片将有更少的框):

在此输入图像描述 (点击放大)

虚线显示原型范围继承.
灰线显示子→父关系(即什么$parent参考).
布朗线显示$$ nextSibling.
灰色框是原始值.蓝框是数组.紫色是物体.

请注意,我在评论中引用的SO答案是在1.0.3出现之前编写的.在1.0.3之前,num当您在文本框中键入时,ngRepeat子范围中的值实际上会发生变化.(这些值在父作用域中不可见.)从1.0.3开始,ngRepeat现在在摘要周期num中用父/ MainCtrl作用域的myNumbers数组中的(未更改的)值替换ngRepeat作用域值.这实质上使输入无法实现.

修复是使用MainCtrl中的对象数组:

$scope.myNumbers = [ {value: 10}, {value: 20} ];
Run Code Online (Sandbox Code Playgroud)

然后绑定到valuengRepeat中对象的属性:

<div ng-repeat="num in myNumbers">
  <input type="text" ng-model="num.value">
  <div>current scope: {{num.value}}</div>
Run Code Online (Sandbox Code Playgroud)

  • 马克,你的答案已经回答了我想要了解幕后发生的事情的愿望.这是我正在寻找的答案类型.此外,您的其他一些SO答案对我帮助很大.感谢您与AngularJS社区分享您的知识和热情.干杯. (5认同)

seb*_*kem 33

现在,AngularJS的更新版本解决了这个问题,该track by功能允许转发器超过基元:

<div ng-repeat="num in myNumbers track by $index">
  <input type="text" ng-model="myNumbers[$index]">
</div>
Run Code Online (Sandbox Code Playgroud)

每次击键后页面都不会重新绘制,这样可以解决丢失焦点的问题.AngularJS官方文档对此非常模糊和混淆.


Dmi*_*eev 9

似乎Angular无法写入以这种方式定义的模型.使用对初始$ scope属性的引用让它以正确的方式绑定值:

<div ng-repeat="num in myNumbers">
  <input type="text" ng-model="myNumbers[$index]">
</div>
Run Code Online (Sandbox Code Playgroud)

  • 谢谢德米特里.您的解决方案有效,但不完全适用.我可以看到数据绑定正在工作,但是在击键后对输入的关注自动消失是很奇怪的.看看你自己[这里](http://embed.plnkr.co/TWTsFuxeZWWchgALdYss). (4认同)
  • 避免使用`$ index`进入控制器.如果您通过`ngFilter`过滤视图上的数据.由于视图和模型中的数组不同,因此视图的索引不会引用原始数组中的索引. (3认同)

Umu*_*acı 9

ngRepeat使用对源数组的引用.由于integer (Number in js)类型,而不是引用类型,因此无法通过javascript中的引用传递.此更改不会传播.

这是一个演示:

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

   var y = x;
   var oy = ox;

   y = 15
   oy.value = 15;
Run Code Online (Sandbox Code Playgroud)

x和的价值是ox什么?

>> x = 10;
>> y = 15;
>> ox = {value:15};
>> oy = {value:15};
Run Code Online (Sandbox Code Playgroud)

所有javascript对象都通过引用传递,所有原语都通过值["string","number"等]传递.

工作人员http://plnkr.co/edit/7uG2IvAdC2sAEHbdHG58


aid*_*dan 9

我有一个类似的问题(并且还需要'添加'和'删除'功能),并解决了这样的问题:

$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>
Run Code Online (Sandbox Code Playgroud)