【问题标题】:angularjs sortable - update sort order propertyangularjs sortable - 更新排序顺序属性
【发布时间】:2014-09-09 02:49:20
【问题描述】:

我正在创建一个也使用 jquery ui 可排序的 angularjs 应用程序。我正在寻找一种简洁的方法来根据模型在页面上的位置更新模型上的“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();
                }
            });
        }
    };
});

还有我的“syncOrder”函数:

$scope.syncOrder = function(){
    // some speculation here:
    for(var i in $scope.objects){
        $scope.objects[i].SortOrder = ???;
    }
};

SortOrder 属性存在并在页面加载时设置,但显然它们需要在排序时更新,因此我可以将更新后的设置传递回服务器并保存。有什么想法吗?

谢谢!

【问题讨论】:

标签: jquery angularjs jquery-ui jquery-ui-sortable


【解决方案1】:

首先,我们需要一种方法将元素与模型中的对象联系起来。我们可以通过给转发器中的元素一个 ID 并在排序停止时获取该 ID 来做到这一点。

<ul sortable>
    <li id="elem-{{obj.id}}" ng-repeat="obj in objects">
        { obj.message }}
    </li>
</ul>

现在在我们的指令中,我们需要使用 sortable 的 toArray 方法 (documentation here) 来获取所有元素 ID 及其位置的列表,我们需要将其传递给我们的 syncOrder 函数。

app.directive('sortable', function ($timeout) {
  return function (scope, element, attributes) {
    element.sortable({
        stop: function(event, ui){
            scope.syncOrder(element.sortable('toArray'));
        }
    });
  };
});

现在我们可以修改 syncOrder 函数以迭代模型中的所有对象,然后迭代通过 sortable 传入的数组中的所有元素,比较 ID,并更新模型以反映新位置。

$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;
            }
        });
    });
};

设置完成后,我们还需要做最后一件事。来自 jquery 可排序小部件的stop 事件在角度执行块的外部 执行。换句话说,angular 无法准确地知道 ifwhen 可排序对象将在我们的$scope 上更新其objects 数组。因此,排序时您的视图似乎不会更新;但是如果你遍历你的数组,你会看到数组确实更新了。

我们需要强制 Angular 意识到范围内的对象即将发生变化。为此,我们将在指令中调用 scope.$apply

return function (scope, element, attributes) {
    element.sortable({
        stop: function(event, ui){
            // Without this, angular magic won't happen when the objects array is updated.
            scope.$apply(function () {
                scope.syncOrder(element.sortable('toArray'));
            });
        }
    });
};

Working Demo

【讨论】:

  • 完美的解决方案和很好的解释。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-06
  • 1970-01-01
  • 2015-09-16
  • 2015-05-27
  • 2015-09-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多