我有一个对象数组:
$scope.widgets = [{
col: 0,
name: "Tile 1"
}, {
col: 1,
name: "Tile 2"
}, {
col: 2,
name: "Tile 3"
}];
每个对象都表示为网格内的一个小部件。对于 ng-repeat 的每次迭代,都会在其各自的位置(列,行)创建一个新的小部件:
<li gridster-item="widget" ng-repeat="widget in widgets">
我发现数组中的对象在重新排序时通过 2 路绑定(bind)根据位置(列/行)相应地更改其属性,但它们的索引不反射(reflect)更改。例如,如果用户交换图 block 1(索引 0)和 2(索引 1),属性将被更新,但对象永远不会交换数组中的位置。
Here是我的 fiddle ,它演示了当您在网格中移动图 block 时,“行”和“列”属性会发生变化,但索引永远不会改变。是否可以根据 ng-repeats 项目的当前位置对集合重新排序?
示例: 用户将图 block 2 拖动到图 block 1 的位置。图 block 2 现在应该成为索引 0,图 block 1 现在应该成为索引 1;
最佳答案
基本的解决方案是,您需要定义一个回调,每当您停止拖动其中一个时,都会对 $scope.widgets
数组进行排序。
我有forked your jsFiddle完整的解决方案,但重点如下:
指定拖动回调
将以下键添加到您的 gridster 选项中:
draggable: {
enabled: true,
stop: function (event, $element, widget) {
sortWidgets();
}
}
编写排序代码
如果您使用underscore或lodash ,您可以使用 .sortBy()
函数轻松完成此操作。或者,您也可以在原生 JS 中执行此操作,如下所示:
function sortWidgets() {
$scope.widgets.sort(function (widget1, widget2) {
return position(widget1) - position(widget2);
});
}
function position(widget) {
return (widget.row || 0) * $scope.gridConfig.columns + widget.col;
}
使用 track by 进行 ng-repeat
假设您的实际小部件更复杂,我建议您向 ng-repeat
添加一个 track by
表达式,以便它将为小部件重用相同的 DOM 节点之后排序与之前排序时使用的排序相同。您不妨现在就添加这个小的性能优化,而不是等到事情变得缓慢。
关于javascript - ng-repeat 可以在重新排序期间修改内部集合的索引吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26921824/