42

这是我的问题的演示。

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

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

谁能向我解释为什么输入不可编辑/只读?如果是设计使然,背后的原理是什么?

2014 年 2 月 20 日更新

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

4

5 回答 5

67

谁能向我解释为什么输入不可编辑/只读?如果是设计使然,背后的原理是什么?

从Angular 1.0.3 开始,这是设计使然。当您“直接绑定到每个 ng-repeat 项目”时,Artem 对 1.0.3+ 的工作方式有很好的解释– 即,

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

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

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

虚线显示原型范围继承。
灰线显示子→父关系(即,什么$parent引用)。
棕色线显示 $$nextSibling。
灰色框是原始值。蓝色框是数组。紫色是物体。

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

解决方法是在 MainCtrl 中使用对象数组:

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

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

<div ng-repeat="num in myNumbers">
  <input type="text" ng-model="num.value">
  <div>current scope: {{num.value}}</div>
于 2013-03-19T03:21:10.330 回答
34

这个问题现在由更新版本的 AngularJS 解决,该版本track by具有允许在原语上重复的功能:

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

每次按键后页面不会重新绘制,解决了失去焦点的问题。官方的 AngularJS 文档对此非常模糊和混乱。

于 2014-02-19T16:28:31.160 回答
9

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

<div ng-repeat="num in myNumbers">
  <input type="text" ng-model="myNumbers[$index]">
</div>
于 2013-03-18T22:54:33.983 回答
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;

x和的值是ox多少?

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

所有 javascript 对象都通过引用传递,所有原语都通过值传递[“字符串”、“数字”等]。

工作 plunker http://plnkr.co/edit/7uG2IvAdC2sAEHbdHG58

于 2013-03-18T23:06:16.693 回答
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>
于 2013-12-18T05:23:02.723 回答