Drag object into sortable list - AngularJS

后端 未结 2 454
轮回少年
轮回少年 2021-02-01 08:08

Problem:

I\'m trying to recreate the Draggable + Sortable functionality from jQuery and can\'t get the dropped element to go into my array of objects.

I want t

相关标签:
2条回答
  • 2021-02-01 08:48

    There is no angular-magic that can help you find the position of a new or moved element, but it's easy to do with jQuery. I've created an example of the jQueryUI-demo wrapping sortable and draggable in directives:

    http://plnkr.co/edit/aSOlqR0UwBOXgpQSFKOH?p=preview

    <ul>
      <li my-draggable="#sortable" class="ui-state-highlight">Drag me down</li>
    </ul>
    
    <ul my-sortable id="sortable">
      <li class="ui-state-default" ng-repeat="item in items">{{item.name}}</li>
    </ul>
    

    Value of my my-draggable is the id to the corresponding my-sortable-element. my-draggable is otherwise pretty straight forward:

    app.directive('myDraggable',function(){
    
      return {
        link:function(scope,el,attrs){
          el.draggable({
            connectToSortable: attrs.myDraggable,
            helper: "clone",
            revert: "invalid"
        });
        el.disableSelection();
        }
      }
    })
    

    In my-sortable I listen to the deactivate event which indicates that an element has been dropped. from is the position of the element in the array that is the source of ng-repeat. ng-repeat creates a child scope for each element with an $index variable indicating the position of the current element in the array. If $index is undefined I know that it's a new element (might be a better way to determine this, but it works for this example). to is the new position of the item. I $emit a 'my-sorted' event if an existing element was moved or a 'my-created' event if a new item was added.

    app.directive('mySortable',function(){
      return {
        link:function(scope,el,attrs){
          el.sortable({
            revert: true
          });
          el.disableSelection();
    
          el.on( "sortdeactivate", function( event, ui ) { 
            var from = angular.element(ui.item).scope().$index;
            var to = el.children().index(ui.item);
            if(to>=0){
              scope.$apply(function(){
                if(from>=0){
                  scope.$emit('my-sorted', {from:from,to:to});
                }else{
                  scope.$emit('my-created', {to:to, name:ui.item.text()});
                  ui.item.remove();
                }
              })
            }
          } );
        }
      }
    })
    

    In the controller I create the items-array and listen to the events:

    $scope.items = [
      {name:'Item 1'},
      {name:'Item 2'},
      {name:'Item 3'},
      {name:'Item 4'},
    ];
    
    $scope.$on('my-sorted',function(ev,val){
      // rearrange $scope.items
      $scope.items.splice(val.to, 0, $scope.items.splice(val.from, 1)[0]);
    })
    
    $scope.$on('my-created',function(ev,val){
      // create new item at position 
      $scope.items.splice(val.to, 0,
        {name:'#'+($scope.items.length+1)+': '+val.name});
    })
    

    As you can see, when you add or move an element the model in the scope gets updated.

    These directives are not very general - you might have to do some adjustment to get them to work with your application.

    0 讨论(0)
  • 2021-02-01 08:50

    You should be able to do every thing you need in your link function.

    myapp.directive("menuDrag", function () {
    
        return{
            restrict: "A",
            link:     function (scope, element, attrs) {
                var item = $(".draggable").draggable(
                    {
                        snap:   true,
                        revert: false,
                        // scope:".dropable"
                        //scope: "tasks"
                    }
                )
                var target = $(".dropable").droppable({
    
                    greedy:     true,
                    hoverClass: "warning",
                    accept:     ".draggable"
                })
    
    
                item.on("drag", function (evt) {
                    item.css = ('background-color', 'red');
                    //evt.stopPropagation();
                    //evt.preventDefault();
                })
    
    
                target.on("over", function (evt) {
    
                    target.css('background-color', 'blue')
    
                    return false;
                });
                target.on("out", function (evt) {
                    dropBox.css('background_color', 'red');
    
    
                    return false;
                });
                target.on("drop", function (evt) {
                    alert("Droped");
                    return false;
                });
                //dragEnterLeave(evt);
            }
        }
    })
    
    0 讨论(0)
提交回复
热议问题