0

I faced with unexpected behavior while using jquery sortable in conjunction with angular ng repeat directive. I'm trying to sort items inside different columns in a table.

When I'm dragging 1st element of 2nd column to 1st position (or to 2nd position) in 1st column - all is OK, but if I'll try to put 1st element of 2nd column to 3rd or 4th position it just goes away with subsequent elements.

If you would look at json encoded array at the bottom of document you will see that components are correctly sorted.

I would be grateful for any kind of assistance.

Here is live example: http://plnkr.co/edit/j6xMb4vhcUDVk8POjzpW?p=preview

HTML

<div data-ng-app="myApp" data-ng-controller="defaultCtrl">
    <table border="1" data-dnd-list="doc">
        <tr>
            <td data-ng-repeat="column in doc.columns" data-index="{{$index}}" class="column">
                <table class="item" style="border:1px solid red; cursor: pointer" width="100%" data-ng-repeat="component in column.components" data-index="{{$index}}">
                    <tr>
                        <td style="padding:5px">{{ component.content }}</td>
                    </tr>
                </table>
            </td>
        </tr>
    </table>
    {{ doc }}
</div>

JS

var app = angular.module("myApp", []);
    app.controller("defaultCtrl", ["$scope", function($scope) {
        $scope.doc = {
            columns: [
                {
                    components: [
                        {
                            content: "1 column 1 component"
                        },
                        {
                            content: "1 column 2 component"
                        },
                        {
                            content: "1 column 3 component"
                        }
                    ]
                },
                {
                    components: [
                        {
                            content: "2 column 1 component"
                        }
                    ]
                }
            ]
        }

    }]);

    app.directive('dndList', function() {
        return function(scope, element, attrs) {
            var toUpdate;
            var oldComponentIndex = -1;
            var oldColumnIndex = -1;

            scope.$watch(attrs.dndList, function(value) {
                toUpdate = value;
                console.log("New changes: ", toUpdate);
            },true);

            $(element[0]).sortable({
                items:'.item',
                start:function (event, ui) {
                    var i = $(ui.item);
                    // on start we define where the item is dragged from
                    oldComponentIndex = i.attr("data-index");
                    oldColumnIndex = i.closest(".column").attr("data-index");
                },
                stop:function (event, ui) {
                    var i = $(ui.item);

                    var newComponentIndex = i.index();
                    var newColumnIndex = i.closest(".column").attr("data-index");

                    var toMove = toUpdate.columns[oldColumnIndex].components[oldComponentIndex];
                    toUpdate.columns[oldColumnIndex].components.splice(oldComponentIndex, 1);
                    toUpdate.columns[newColumnIndex].components.splice(newComponentIndex, 0, toMove);

                    scope.$apply(scope.doc);
                }
            })
        }
    });

1 Answer 1

2

OK. I found a solution. The fact is that when you put new item in sortable list, the DOM became unsynchronized with AngularJS. To prevent this you need to remove HTML of new item.

i.remove();

Here is updated plunker. http://plnkr.co/edit/j6xMb4vhcUDVk8POjzpW?p=preview

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.