14

问题:

我正在尝试从 jQuery 重新创建 Draggable + Sortable 功能,但无法让删除的元素进入我的对象数组。

我想将一个$.draggable()按钮拖到$.sortable()列表中。我希望按钮代表具有属性的对象(可以是关联数组或对象本身),当我将其放入列表中时,我希望它将自身放入数组中的位置。


为了清楚起见,我在左侧的菜单中有一系列潜在对象。在右侧,我使用$http调用我的 API 来检索包含所有字段的表单$scope。我希望将潜在对象(如 a textarea)放入该表单的字段中的放置位置。

jquery 位很简​​单,但$scope数组中位置不存在的对象是问题所在。


我试过的:

我很接近混合梳理ui-sortable$.draggable指令包装器,但我的代码运行得不是很好。


例子:


更新1:

ui-sortable我已经使用like 指令与 wraps 指令相结合取得了进展$.draggable(),有点难看但有效。

更新 2:

我现在可以使用它,但是我从 jquery 中获取索引并使用 PHP 将其切片到该位置,然后重新加载整个列表。谈跛脚一定有更好的办法。

更新 3:

这是为任何人的应用程序模块化的工作示例

4

2 回答 2

18

没有 angular-magic 可以帮助您找到新元素或移动元素的位置,但使用 jQuery 很容易做到。我创建了一个 jQueryUI-demo 示例,在指令中包装可排序和可拖动:

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>

my 的值my-draggable是对应元素的 id my-sortable。my-draggable 在其他方面非常简单:

app.directive('myDraggable',function(){

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

my-sortable我听deactivate指示元素已被删除的事件。from是数组中作为 ng-repeat 源的元素的位置。ng-repeat 为每个元素创建一个子作用域,其中 $index 变量指示当前元素在数组中的位置。如果 $index 未定义,我知道它是一个新元素(可能是确定这一点的更好方法,但它适用于本示例)。to是项目的新位置。如果移动了现有元素,我会发出“my-sorted”事件,如果添加了新元素,则会发出“my-created”事件。

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

在控制器中,我创建 items-array 并监听事件:

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

如您所见,当您添加或移动元素时,范围内的模型会更新。

这些指令不是很通用 - 您可能需要进行一些调整才能让它们与您的应用程序一起使用。

于 2013-09-24T09:46:08.187 回答
1

您应该能够在链接功能中做所有您需要的事情。

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);
        }
    }
})
于 2013-09-19T00:59:21.993 回答