将对象拖入可排序列表 - AngularJS

Posted

技术标签:

【中文标题】将对象拖入可排序列表 - AngularJS【英文标题】:Drag object into sortable list - AngularJS 【发布时间】:2013-09-21 01:14:25 【问题描述】:

问题:

我正在尝试从 jQuery 重新创建 Draggable + Sortable 功能,但无法将放置的元素放入我的对象数组中。

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


为了清楚起见,我在左侧的菜单中有一组 潜在 对象。在右边,我使用$http 调用我的API 来检索一个表单,该表单的所有字段都保存在$scope 中。我希望将潜在对象(如textarea)拖放到该表单的字段中的拖放位置。

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


我尝试过的:

我很接近混合组合 ui-sortable$.draggable 指令包装器,但我的代码运行不佳。


示例:

KnockoutJS Example jQuery demo

更新 1:

我在 ui-sortable like 指令与包装 $.draggable() 的指令相结合方面取得了进展,有点难看但有效。

更新 2:

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

更新 3:

这是一个为任何人的应用程序模块化的工作example。

【问题讨论】:

你绝对应该做一个小提琴手,这是很多代码要整理。 @ZackArgyle 我刚刚澄清了我的问题。该代码不起作用,但我希望它可能会有所帮助。 我可能错了,Angular UI 没有可拖动指令吗? @ErikHonn 他们有 ui-sortable github.com/angular-ui/ui-sortable 这是问题的一半。 在某处有您的代码示例吗?我不确定我是否理解。从视觉上看,用户如何知道他们将物品放在哪里? DOM 中是否有用于放置对象的占位符元素? 【参考方案1】:

没有 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-draggable 的值是对应my-sortable 元素的id。 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);
)

如您所见,当您添加或移动元素时,作用域中的模型会更新。

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

【讨论】:

太棒了!一旦我用这个替换我现有的设置并用链接更新我的问题,我就会把它变成一个 Github 存储库。 @MichaelCalkins 你还打算在 github 上发布这个吗? @joakimbl 我只是学习角度但如果我将它们交换为输入并修改它们的值,为什么它不在 $scope.items 中更新? plnkr.co/edit/4lztv66RfnJAnIcMlPNs?p=preview @turbo2oh 我完全忘记了这一点,但我必须重建我需要的功能,因为我将把一些东西放到github.com/clouddueling/angular-common @turbo2oh 你可以在这里找到一个例子clouddueling.github.io/angular-common【参考方案2】:

你应该能够在你的链接函数中做你需要做的每一件事。

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

【讨论】:

如何将对象添加到 $scope 中保存的表单对象中?如果我没记错的话,我在这里只看到 jquery 片段。

以上是关于将对象拖入可排序列表 - AngularJS的主要内容,如果未能解决你的问题,请参考以下文章

结合 AngularJS、jQueryUI、Angular-Drag-Drop 进行排序列表

使用 angularjs 列出重新排序动画

嵌套可排序 AngularJS

小白如何使用Axure制作列表排序

jQuery UI - 放置事件后克隆可放置/可排序列表

angularjs按空格对象排序