我正在创建一个angularjs应用程序,它也使用jquery ui sortable。我正在寻找一种干净的方式来更新" SortOrder"我的模型上的属性基于它们在页面上的位置,每次执行排序。
这是我到目前为止所拥有的:
<div class="object-container" sortable>
<div ng-repeat="object in objects">
<div class="obj-title">{{object.Title}}</div>
</div>
</div>
这是我的可排序指令:
myApp.directive('sortable', function(){
return {
restrict : 'A',
link : function(scope, element, attributes){
element.sortable({
helper : 'clone',
stop : function(event, ui){
scope.syncOrder();
}
});
}
};
});
我的&#34; syncOrder&#34;功能:
$scope.syncOrder = function(){
// some speculation here:
for(var i in $scope.objects){
$scope.objects[i].SortOrder = ???;
}
};
SortOrder属性存在并在页面加载时设置,但显然它们需要在排序时更新,因此我可以将更新的集合传递回服务器并保存。有什么想法吗?
谢谢!
答案 0 :(得分:6)
首先,我们需要一种方法将元素绑定到模型中的对象。我们可以通过在转发器中为我们的元素提供ID并在排序停止时获取该ID来实现此目的。
<ul sortable>
<li id="elem-{{obj.id}}" ng-repeat="obj in objects">
{ obj.message }}
</li>
</ul>
现在,在我们的指令中,我们需要使用可排序的toArray
方法(documentation here)来获取所有元素ID及其位置的列表,我们需要将其传递给我们的{ {1}}功能。
syncOrder
现在我们可以修改我们的app.directive('sortable', function ($timeout) {
return function (scope, element, attributes) {
element.sortable({
stop: function(event, ui){
scope.syncOrder(element.sortable('toArray'));
}
});
};
});
函数来遍历模型中的所有对象,然后迭代通过sortable传入的数组中的所有元素,比较ID,并更新模型以反映新的位置。
syncOrder
一旦我们完成了这个设置,我们需要做的最后一件事。来自jquery可排序窗口小部件的$scope.syncOrder = function (elemPositions) {
// loop over our model objects
$scope.objects.forEach(function (obj) {
// loop over all the element positions
elemPositions.forEach(function (elemId, index) {
// shave off the string part of the ID on the element.
var id = parseInt(elemId.replace(/elem-/, ''));
// Items in the elemPositions array are in the order that they
// are on the page. If the element ID matches the ID we gave to
// our object, update the sort order to match the current index.
if (id === obj.id) {
obj.sortOrder = index;
}
});
});
};
事件在角度执行块的外部执行。换句话说,当 可排序将更新我们stop
上的objects
数组时,angular无法确切地知道 if 或。因此,您的视图在排序时似乎不会更新;虽然如果你遍历你的数组,你会看到数组确实更新了。
我们需要强制角度来意识到变化即将发生在范围内的对象上。为此,我们将在我们的指令中调用$scope
。
scope.$apply