Drag and drop sortable ng:repeats in AngularJS?

后端 未结 5 1509
伪装坚强ぢ
伪装坚强ぢ 2020-12-12 09:29

Is it at all easy to use jQuery.sortable on ng-repeat elements in AngularJS?


It would be awesome i

相关标签:
5条回答
  • 2020-12-12 10:18

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

    • https://github.com/schartier/angular-sortable
    0 讨论(0)
  • 2020-12-12 10:26

    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

    Demo for ng-sortable

    0 讨论(0)
  • This is how I am doing it with angular v0.10.6. Here is the 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();
                }
            });
        };
    });
    
    0 讨论(0)
  • 2020-12-12 10:33

    Angular UI has a sortable directive,Click Here for Demo

    Code located at ui-sortable, usage:

    <ul ui-sortable ng-model="items">
      <li ng-repeat="item in items">{{ item }}</li>
    </ul>
    
    0 讨论(0)
  • 2020-12-12 10:34

    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 angular gets desynchronized from the DOM.

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

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

    0 讨论(0)
提交回复
热议问题