Javascript 在 AngularJS 中拖放可排序的 ng:repeats?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7354992/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 01:57:11  来源:igfitidea点击:

Drag and drop sortable ng:repeats in AngularJS?

javascriptangularjsjquery-ui-sortable

提问by Nick Retallack

Is it at all easy to use jQuery.sortableon ng-repeatelements in AngularJS?

在 AngularJS 中的元素上使用jQuery.sortable起来容易ng-repeat吗?



It would be awesome if re-ordering the items automatically propagated that ordering back into the source array. I'm afraid the two systems would fight though. Is there a better way to do this?

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

回答by Guillaume86

Angular UI has a sortable directive,Click Here for Demo

Angular UI 有一个可排序的指令,点击这里查看演示

Code located at ui-sortable, usage:

代码位于ui-sortable,用法:

<ul ui-sortable ng-model="items">
  <li ng-repeat="item in items">{{ item }}</li>
</ul>

回答by Manuel Woelker

I tried to do the same and came up with the following solution:

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

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

Used like this:

像这样使用:

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

It seems to work fairly well. The trick is to undo the DOM manipulation made by sortable before updating the model, otherwise agular gets desynchronized from the DOM.

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

Notification of the changes works via the my:onsort expression which can call the controller methods.

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

I created a JsFiddle based on the angular todo tutorial to shows how it works: http://jsfiddle.net/M8YnR/180/

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

回答by respectTheCode

This is how I am doing it with angular v0.10.6. Here is the jsfiddle

这就是我使用 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();
            }
        });
    };
});

回答by Sebastien Chartier

Here's my implementation of sortable Angular.js directive without jquery.ui :

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

回答by Dheeraj Nalawade

you can go for ng-sortable directive which is lightweight and it does not uses jquery. here is link ng-sortable drag and drop elements

你可以选择轻量级的 ng-sortable 指令,它不使用 jquery。这是链接ng-sortable 拖放元素

Demo for ng-sortable

ng-sortable 演示