AngularJS:当元素的 属性 改变时强制 ng-repeat 更新
AngularJS: Force ng-repeat update when property of an element changes
我正在努力研究 angular 观察数组的方式。我有以下标记:
<map name="theMap" center="{{mapInfo.center.toUrlValue()}}" zoom="{{mapInfo.zoom}}" on-dragend="dragEnd()" on-zoom_changed="zoomChanged()">
<marker ng-repeat="pin in pins() track by pin.iconKey()" position="{{pin.latitude}}, {{pin.longitude}}" title="{{pin.streetAddress}}" pinindex="{{$index}}" on-click="click()"
icon="{{pin.icon()}}"></marker>
</map>
pins() 返回的每个引脚都有许多属性、子属性等。其中一个子属性控制标记颜色。当那个 sub属性 改变时,我希望 UI 更新。
因为 ng-repeat 显示为 $watch 基于对集合的简单更改,所以如何实现它并不明显。我认为我的跟踪函数 iconKey() 会执行此操作,因为它 returns 一个不同的值,具体取决于 sub属性 的值。但这没有用。
另一件事:sub属性 在指令下运行的 $interval 的回调中被更改。我提到这个是因为,在较早的 post 中,有人认为可能存在 context/scope 问题。
然而,即使我在 UI 的控制器中更改了事件侦听器(在 $interval 回调的 "success" 子句中引发了事件),它仍然没有工作。
这就是为什么我认为问题只是 angular 没有注意到 iconKey() 的变化;它的行为就像它 $watches for ng-repeat 是数组的长度。当 sub属性 改变时,它不会改变。
更新
我创建了一个 plunker 来演示我面临的问题。您可以在 http://plnkr.co/edit/50idft4qaxqw1CduYkOd
找到它
这是我正在构建的应用程序的精简版,但它包含基本元素(例如,一个数据上下文服务来保存有关地图图钉的信息和一个 $interval 服务来切换子属性 引脚数组元素之一)。
您可以通过单击菜单栏中的“开始”来启动更新周期(您可能需要稍微向下拖动地图以将两个图钉置于全视图中)。它应该切换每个图钉的颜色,或者,每次切换 5 次,每 2 秒一次。它通过在控制器中定义的侦听器中切换 pin 对象的 isDirty 属性 的值来实现这一点。该事件由 $interval 服务引发。
如果您在测试周期中在第 22 行中断,您将看到图钉图标被返回。所以 angular 中的某些东西正在调用信息...但是图钉颜色没有改变。
我期待有人迅速指出与我的任何理论无关的愚蠢错误:)。提前为我戴的任何眼罩道歉。
更新 2
检查响应中的代码片段后,我简化了我的 plnkr 并证明 angular 实际上是在子 属性 更改时更新 UI。所以这似乎是 ng-map 中的限制或错误。
您在这里缺少的是数组和函数的概念,您的函数 pins() 传递一个数组,并且该数组已与 ng-repeat 绑定。但这里的残酷事实是,无论该数组是什么都不会改变,因为您没有对该数组的任何引用,因此 rg-repeat 将始终保持原样...
我建议尝试通过两种方式引用数组
ng-init="pinsArray = pins()"
和第二个内部控制器
$scope.pinsArray = $scope.pins()
然后在 controller
中对 $scope.pinsArray 进行更改
ng-repeat 将更改为
ng-repeat="pin in pinsArray"
另请阅读有关过滤器的信息,我猜这就是您尝试使用 "track by"
进行的操作
希望这对您有所帮助..
编辑:使用 ngMap 标记的不同故事
好像没看子属性。
所以这里有一个解决方法
添加以下语句以在更改其属性后更新 pinsArray。
pinsArray = angular.copy(pinsArray);
已解决的 plnkr 示例:
http://plnkr.co/edit/EnW1RjE9v47nDpynAZLK?p=preview
我正在努力研究 angular 观察数组的方式。我有以下标记:
<map name="theMap" center="{{mapInfo.center.toUrlValue()}}" zoom="{{mapInfo.zoom}}" on-dragend="dragEnd()" on-zoom_changed="zoomChanged()">
<marker ng-repeat="pin in pins() track by pin.iconKey()" position="{{pin.latitude}}, {{pin.longitude}}" title="{{pin.streetAddress}}" pinindex="{{$index}}" on-click="click()"
icon="{{pin.icon()}}"></marker>
</map>
pins() 返回的每个引脚都有许多属性、子属性等。其中一个子属性控制标记颜色。当那个 sub属性 改变时,我希望 UI 更新。
因为 ng-repeat 显示为 $watch 基于对集合的简单更改,所以如何实现它并不明显。我认为我的跟踪函数 iconKey() 会执行此操作,因为它 returns 一个不同的值,具体取决于 sub属性 的值。但这没有用。
另一件事:sub属性 在指令下运行的 $interval 的回调中被更改。我提到这个是因为,在较早的 post 中,有人认为可能存在 context/scope 问题。
然而,即使我在 UI 的控制器中更改了事件侦听器(在 $interval 回调的 "success" 子句中引发了事件),它仍然没有工作。
这就是为什么我认为问题只是 angular 没有注意到 iconKey() 的变化;它的行为就像它 $watches for ng-repeat 是数组的长度。当 sub属性 改变时,它不会改变。
更新
我创建了一个 plunker 来演示我面临的问题。您可以在 http://plnkr.co/edit/50idft4qaxqw1CduYkOd
找到它这是我正在构建的应用程序的精简版,但它包含基本元素(例如,一个数据上下文服务来保存有关地图图钉的信息和一个 $interval 服务来切换子属性 引脚数组元素之一)。
您可以通过单击菜单栏中的“开始”来启动更新周期(您可能需要稍微向下拖动地图以将两个图钉置于全视图中)。它应该切换每个图钉的颜色,或者,每次切换 5 次,每 2 秒一次。它通过在控制器中定义的侦听器中切换 pin 对象的 isDirty 属性 的值来实现这一点。该事件由 $interval 服务引发。
如果您在测试周期中在第 22 行中断,您将看到图钉图标被返回。所以 angular 中的某些东西正在调用信息...但是图钉颜色没有改变。
我期待有人迅速指出与我的任何理论无关的愚蠢错误:)。提前为我戴的任何眼罩道歉。
更新 2
检查响应中的代码片段后,我简化了我的 plnkr 并证明 angular 实际上是在子 属性 更改时更新 UI。所以这似乎是 ng-map 中的限制或错误。
您在这里缺少的是数组和函数的概念,您的函数 pins() 传递一个数组,并且该数组已与 ng-repeat 绑定。但这里的残酷事实是,无论该数组是什么都不会改变,因为您没有对该数组的任何引用,因此 rg-repeat 将始终保持原样...
我建议尝试通过两种方式引用数组
ng-init="pinsArray = pins()"
和第二个内部控制器
$scope.pinsArray = $scope.pins()
然后在 controller
中对 $scope.pinsArray 进行更改ng-repeat 将更改为
ng-repeat="pin in pinsArray"
另请阅读有关过滤器的信息,我猜这就是您尝试使用 "track by"
进行的操作希望这对您有所帮助..
编辑:使用 ngMap 标记的不同故事
好像没看子属性。 所以这里有一个解决方法
添加以下语句以在更改其属性后更新 pinsArray。
pinsArray = angular.copy(pinsArray);
已解决的 plnkr 示例: http://plnkr.co/edit/EnW1RjE9v47nDpynAZLK?p=preview