Stack Overflow is a community of 4.7 million programmers, just like you, helping each other.

Join them; it only takes a minute:

Sign up
Join the Stack Overflow community to:
  1. Ask programming questions
  2. Answer and help your peers
  3. Get recognized for your expertise

I've got a AngularJS directive that hooks up sortables.

I'm trying to create a directive that will allow me to drag and drop new items into a sortable. If that item is a 'section' it should allow further drag and drops into it recursively. The section inits a sortable itself and I attempt to connect the sortables. Problem is it never connects... I've built similar demos with jqueryUI alone so I know that its possible, my angular implementation is probably just messing something up. Any ideas?

sortable directive:

app.constant('sortableConfig', {
    connectWith: '.sortables'
});

app.directive('sortable', ['$timeout','sortableConfig', function ($timeout, sortableConfig) {
    return {
        restrict: 'AE',
        scope: {
            ngModel: '=',
            options: '='
        },
        link: function ($scope, $element, $attributes) {
            var ngModel = $scope.ngModel;

            var options = angular.extend(sortableConfig, 
                    $scope.$eval($attributes.options)),
                sortableIn = 0;

            console.log(ngModel)

            options.start = function(e, ui) {
                // Save position of dragged item
                ui.item.sortable = { index: ui.item.index() };
            };

            options.update = function(e, ui) {
                // For some reason the reference to ngModel in stop() is wrong
                ui.item.sortable.resort = ngModel;
            };

            options.receive = function(e, ui) {
                sortableIn = 1;
                ui.item.sortable.relocate = true;
                // added item to array into correct position and set up flag
                ngModel.splice(ui.item.index(), 0, ui.item.sortable.moved);
            };

            options.remove = function(e, ui) {
                // copy data into item
                if (ngModel.length === 1) {
                    ui.item.sortable.moved = ngModel.splice(0, 1)[0];
                } else {
                    ui.item.sortable.moved =  ngModel.splice(ui.item.sortable.index, 1)[0];
                }
            };

            options.over = function(e, ui) {
                sortableIn = 1;
            };

            options.out = function(e, ui) {
                sortableIn = 0;
            };

            options.beforeStop = function(e, ui) {
                // http://snipplr.com/view/49923/
                if (sortableIn == 0) { 
                    console.log('REMOVE!', ui.item.sortable.resort)
                    //ui.item.remove(); 
                    //ngModel.splice(ui.item.index(), 1);
                }
            };

            options.stop = function(e, ui) {
                // digest all prepared changes
                if (ui.item.sortable.resort && !ui.item.sortable.relocate) {
                    // Fetch saved and current position of dropped element
                    var end, start;
                    start = ui.item.sortable.index;
                    end = ui.item.index();

                    // Reorder array and apply change to scope
                    ui.item.sortable.resort.splice(
                        end, 0, ui.item.sortable.resort.splice(start, 1)[0]);
                }
            };

            $timeout(function(){
                console.log(options)
                $element.sortable(options);
            })
        }
    }
}]);

sortable template:

 <ul sortable class="sortable" ng-model="ngModel">
<li class="pull-left" ng-repeat="item in ngModel" ng-model="item" ng-style="drawLayout(item)">
    <div ng-if="isField(item)"
         class="btn btn-info btn-draggable layout-field"
         ng-click="showDetails(item)">{{item.name}}</div>

    <div droppable 
         ng-model="item.children"
         dropped="layoutDropped(dragModel, dropModel)" 
         ng-if="item.typeOf == 'section'"
         class="panel panel-default layout-section">

        <div class="panel-heading" ng-click="showDetails(item)">
            {{item.name}}
            <div ng-show="item.helpTextOpt != 'none'">
                <hr />
                <p>{{item.helpText}}</p>
            </div>
        </div>
        <div class="panel-body" onload="ngModel=item.children"
             ng-include="'views/app-builder/layout.html'">
        </div>
    </div>
</li>
share|improve this question
    
suggest using nested sortable plugin which is an extension of jQuery UI sortable. A demo in plunker or jsfiddle.net would help – charlietfl Nov 17 '13 at 17:28
    
Ya, found a few ... any you would recommend? – amcdnl Nov 17 '13 at 17:46
    
only know of one...never had problems with it, haven't used for long time – charlietfl Nov 17 '13 at 17:52

You could reference the code of Angular-NestedSortable(https://github.com/JimLiu/Angular-NestedSortable). An Angularjs ui component that can sort nested lists and bind data, and it dosen't need to depend on jQuery.

share|improve this answer
up vote 0 down vote accepted

I was able to come up with a solution that uses jQueryUI's sortable and can hook into draggable and droppable. Full details here

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.