【问题标题】:Drag and drop sortable ng:repeats in AngularJS?在AngularJS中拖放可排序的ng:重复?
【发布时间】:2011-11-13 09:01:07
【问题描述】:

在 AngularJS 中的 ng-repeat 元素上使用 jQuery.sortable 是否容易?


如果重新排序项目会自动将该排序传播回源数组,那就太棒了。恐怕这两个系统会打架。有没有更好的方法来做到这一点?

【问题讨论】:

  • 您是否可以更新 Angular js 当前版本的 js fiddle 代码,即 Angular js 1.0.1。我尝试通过根据我的要求将 angular js 的版本更改为 1.0.1 来在 jsfiddle 上运行示例,但随后代码中断并且不起作用。请帮忙。谢谢!
  • 我同意这一点。还在寻找 1.0.1 的工作示例 :-)
  • 找到了这个,在 1.0.1 中工作 - jsfiddle.net/007design/KHqbM
  • 我创建了一个教程,介绍如何结合 JQuery UI 执行此操作。使用单个指令很容易做到。解释和例子可以在这里找到:smartjava.org/content/drag-and-drop-angularjs-using-jquery-ui

标签: javascript angularjs jquery-ui-sortable


【解决方案1】:

Angular UI 有一个可排序的指令,Click Here for Demo

代码位于ui-sortable,用法:

<ul ui-sortable ng-model="items" ui-sortable-update="sorted">
  <li ng-repeat="item in items track by $index" id="{{$index}}">{{ item }}</li>
</ul>
$scope.sorted = (event, ui) => { console.log(ui.item[0].getAttribute('id')) }

【讨论】:

  • 请注意,您应该添加ng-modelui:sortable&lt;ul ui:sortable ng:model="list"&gt;
  • 控制台有错误吗?在我的 chrome/windows 7 中工作,您可以尝试更新库(jquery/jqueryUI/angular/angularUI),看看它是否解决了您的问题...
  • jsfiddle 示例似乎不能可靠地工作。没有错误,但订单间歇性地变得不同步。在 Firefox 和 chrome 中尝试过
  • 知道如何在没有 jQuery 的情况下实现这一目标吗?
  • @Kugel 你有没有尝试过 angular-ui sortable 的最后一个版本?以角度发展的速度,演示很快就会过时:github.com/angular-ui/ui-sortable
【解决方案2】:

我尝试做同样的事情并想出了以下解决方案:

angular.directive("my:sortable", function(expression, compiledElement){
    return function(linkElement){
        var scope = this;
        linkElement.sortable(
        {
            placeholder: "ui-state-highlight",
            opacity: 0.8,
            update: function(event, ui) {
                var model = scope.$tryEval(expression);
                var newModel = [];
                var items = [];
                linkElement.children().each(function() {
                    var item = $(this);
                    // get old item index
                    var oldIndex = item.attr("ng:repeat-index");
                    if(oldIndex) {
                        // new model in new order
                        newModel.push(model[oldIndex]);
                        // items in original order
                        items[oldIndex] = item;
                        // and remove
                        item.detach();
                    }
                });
                // restore original dom order, so angular does not get confused
                linkElement.append.apply(linkElement,items);

                // clear old list
                model.length = 0;
                // add elements in new order
                model.push.apply(model, newModel);

                // presto
                scope.$eval();

                // Notify event handler
                var onSortExpression = linkElement.attr("my:onsort");
                if(onSortExpression) {
                    scope.$tryEval(onSortExpression, linkElement);
                }
            }
        });
    };
});

这样使用:

<ol id="todoList" my:sortable="todos" my:onsort="onSort()">

它似乎工作得很好。诀窍是在更新模型之前撤消 sortable 所做的 DOM 操作,否则 angular 会与 DOM 不同步。

更改通知通过可调用控制器方法的 my:onsort 表达式工作。

我根据 angular todo 教程创建了一个 JsFiddle 来展示它是如何工作的:http://jsfiddle.net/M8YnR/180/

【讨论】:

    【解决方案3】:

    这就是我使用 Angular v0.10.6 的方式。这是jsfiddle

    angular.directive("my:sortable", function(expression, compiledElement){
        // add my:sortable-index to children so we know the index in the model
        compiledElement.children().attr("my:sortable-index","{{$index}}");
    
        return function(linkElement){
            var scope = this;            
    
            linkElement.sortable({
                placeholder: "placeholder",
                opacity: 0.8,
                axis: "y",
                update: function(event, ui) {
                    // get model
                    var model = scope.$apply(expression);
                    // remember its length
                    var modelLength = model.length;
                    // rember html nodes
                    var items = [];
    
                    // loop through items in new order
                    linkElement.children().each(function(index) {
                        var item = $(this);
    
                        // get old item index
                        var oldIndex = parseInt(item.attr("my:sortable-index"), 10);
    
                        // add item to the end of model
                        model.push(model[oldIndex]);
    
                        if(item.attr("my:sortable-index")) {
                            // items in original order to restore dom
                            items[oldIndex] = item;
                            // and remove item from dom
                            item.detach();
                        }
                    });
    
                    model.splice(0, modelLength);
    
                    // restore original dom order, so angular does not get confused
                    linkElement.append.apply(linkElement,items);
    
                    // notify angular of the change
                    scope.$digest();
                }
            });
        };
    });
    

    【讨论】:

    • 我最终只使用了 SlickGrid,但我相信你的话,这是可行的。
    • 此解决方案需要注意的一点是,它很可能无法像 v1.x 那样工作。调整这个应该不难,但我还没有开始更新我的所有代码。
    • @respectTheCode 您是否重构了代码以使用最新的 AngularJS 版本(v1.0.1)?我一辈子都找不到可靠的 1.0.1 工作版本......
    • @Greg 我们现在正在使用 Angular-UI 的 UI-Sortable,效果很好。 github.com/angular-ui/ui-sortable
    【解决方案4】:

    这是我在没有 jquery.ui 的情况下实现可排序的 Angular.js 指令:

    【讨论】:

      【解决方案5】:

      您可以选择轻量级且不使用 jquery 的 ng-sortable 指令。这是链接ng-sortable drag and drop elements

      Demo for ng-sortable

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-13
        • 2013-09-08
        • 1970-01-01
        • 1970-01-01
        • 2014-07-05
        • 1970-01-01
        相关资源
        最近更新 更多