我正在尝试使用指令创建递归网格布局。
我的问题是当我使用其中的删除按钮删除网格时 - 它会从应用网格容器中删除,但双向数据绑定不能正常工作。代替当前网格,最后一个网格将从UI中删除。
Link- http://plnkr.co/edit/DzKIHKvJdLoZiYY3jgDx?p=preview
重现的步骤: 1)单击第一个网格上的删除按钮,您将看到代替第一个网格,第二个网格被删除。 applygrid的json数据包含其中的第二个网格。因此角度的双向绑定并不像它应该的那样工作。
答案 0 :(得分:2)
我在之前的回答中做了一点思考,结果证明这不正确。
首先,请勿使用track by $index
。在你的情况下没有任何意义。 track by
是ng-repeat
的优化,用于关联数组中的(可能是新的)对象,这些对象是"业务方面的"等于数组中的旧对象,以便它重用范围和DOM元素,以尽量减少DOM操作。也就是说:如果你给ng-repeat
一个提示,说明新数组中的新对象是"等于"对于旧数组中的旧对象,它将重用其范围并跳跃使新对象与旧对象相比没有显着差异,将会触发较少$watch
个回调,并且将发生较少的DOM更新。
你的实际问题是你是静静的"或者"一次性"使用以下语句绑定数据:
$scope.gridIndex = $parse($attrs.gridIndex)($scope);
$scope.gridValues=$parse($attrs.appliedgrid)($scope);
$scope.gridParent=$parse($attrs.appliedgrids)($scope);
确实从数组中删除了第一个grid
项,但ng-repeat
未删除其范围和DOM元素,因为使用了track by $index
。但是,新的0索引对象(之前的第2个)用于更新范围(为第一个对象创建的范围)。
您没有看到这反映在UI上,因为$scope.gridValues
在开始时被评估过,而不会再次评估。
因此,即使$scope.appliedgrid
现在指向[{span:12,data:[object]}]
,$scope.gridValues
仍然指向[{span:6,data:[object]},{span:6,data:[grid2]}]
。
删除track by $index
解决了这个问题,因为ng-repeat
通过引用跟踪对象,因此每个对象都与相同的范围相关联,直到从数组中删除它为止。
您可以使用AngScope验证它,这是一个基于Firebug的小型范围检查器。您必须在单独的选项卡中使用&#34打开它;在单独的窗口中启动预览"为了让它在plunker中工作。
我试图找到一个快速解决方案,但没有运气。我想,你必须使用独立的范围和真正的双向绑定重新编写它。
答案 1 :(得分:1)
简短回答:从track by $index
移除ng-repeat
。
答案很长:当你写track by $index
时,你实际上是在向ng-repeat
说:
从阵列中删除第一个对象时,角度摘要并找出以下内容:
这是因为当ng-repeat
再次运行时,您之前标记为" 1"的第二个对象现在是您的第一个也是唯一一个被标记为" 0&#34的对象;,因为从{0开始再次评估$index
。
Angular认为第一个DOM元素仍然指向同一个对象,因为它发现它被标记为" 0",不管它是一个完全不同的对象。在幕后,$scope
具有正确的模型值,但ng-repeat
会跳过重新呈现DOM元素。
很难写出真正发生的事情。希望我做对了,帮助过你。