根据特定条件拖放列表

Posted

技术标签:

【中文标题】根据特定条件拖放列表【英文标题】:Drag and drop lists based on certain conditions 【发布时间】:2015-10-09 04:38:09 【问题描述】:

我正在为我的 AngularJS 项目使用 angular-drag-and-drop-lists (https://github.com/marceljuenemann/angular-drag-and-drop-lists) 来创建两个允许我执行以下操作的列表:

    将项目从列表 A 拖到列表 B 将项目从列表 B 拖到列表 A 对列表 A 中的项目重新排序 重新排序列表 B 中的项目

使用图书馆网站 (http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/simple) 上的一个简单示例,我可以看到这四个条件很容易实现。然而,当我想引入稍微复杂一点的行为时,事情就开始变得棘手了:

    当将项目从列表 A 拖到列表 B 时,我希望发生一些事情(通过 dnd-drop 回调很容易实现。这目前适用于我 当将项目从列表 B 拖到列表 A 时,我不希望发生除常规放置之外的任何事情(即项目在列表 A 中结束并且没有任何花哨的事情发生)。 目前对我有用 对列表 A 中的项目进行重新排序时,将项目重新放入列表中的新位置时不会发生任何事情(即使它被放回原来的位置)这是我遇到问题的地方- 更多解释见下文 对列表 B 中的项目进行重新排序时,将项目重新放入列表中的新位置时不会发生任何事情(即使它被放回其原始位置)。 目前对我有用

我在很大程度上调整了上面提供的示例链接中使用的示例代码。我遇到的问题是,当我将列表 A 中的项目重新排序时,我想要执行的操作也发生在列表 A 中。

我目前的设置/伪代码如下:

我的清单:

$scope.models.lists = 
    "A": [],
    "B": []

我用从数据库中提取的信息填充这些列表。列表中的每个项目还有一个属性,用于跟踪该项目有多少 children

我的标记如下所示:

<ul dnd-list="list"
    dnd-allowed-types="['itemType']"
    dnd-drop="myCallback(event, index, item, external, type, 'itemType')">
    <li ng-repeat="item in list | filter:searchText"
        dnd-draggable="item"
        dnd-moved="list.splice($index, 1)"
        dnd-effect-allowed="move"
        dnd-selected="models.selected = item"
        dnd-type="'itemType'"
        ng-class="'selected': models.selected === item"
        ng-dblclick="editProperties();">
            item.label + ' - ' + item.description
    </li>
</ul>

我的回调如下所示:

    $scope.myCallback= function(event, index, item, external, type, allowedType) 
        // If the item in question has no children then we don't need to do anything special other than move the item.
        if (item.children.length == 0) 
            return item;
        

        // If moving items around list B then just move them.
        for (var i = 0; i < $scope.models.lists.B.length; i++) 
            if (item.label === $scope.models.lists.B.[i].label)  
                return item;
            
        

        // I only want this code to execute if we know we are moving from list A to list B and the item in question has > 0 children.
        if (item.children.length > 0) 
            // Code that I want to execute only when moving from list A to list B goes here
        

如果有人能够帮助我,我将非常感激。

谢谢!

【问题讨论】:

【参考方案1】:

如果您不完全致力于该库(顺便说一句,它不适用于触摸屏)RubaXa 的 Sortable 就是事实:Sortable

文档很强大,性能非常好,我希望在此之前我没有将时间浪费在其他 DnD 库上。

【讨论】:

我不受图书馆的约束,所以我很乐意去看看。不过,我不能很快看出我给定的用例是否会得到库的支持。你能对此有所了解吗? 我不是完全清楚你在原始问题中要做什么,但它的一些子集应该在我刚刚放在一起的这个例子中:@ 987654322@。当从 A 移动到 B 时,或者在列表之间移动时,当被移动项目的属性(在本例中为计数器)超过您设置的阈值时,它将触发警报。 哇,我真的很感谢你在这里付出的努力!我不确定我如何才能对我的意图不那么模棱两可,但你提出的例子似乎满足了我正在寻找的东西。我只想能够从 A->A、B->B、B->A 移动而不会收到警报,并且从 A->BI 移动时只希望在满足特定条件时发出警报,否则只需执行像平常一样进行常规拖放。 将此标记为已接受的答案,因为您提供的确实回答了我的问题。您到底是如何研究出如何在(几乎)零文档的情况下使用角度指令的?您是否刚刚阅读了源代码并从那里开始工作?如果是这样,干得好! 现在阅读您的消息时不再是半夜,它不再那么模棱两可了 :-) 我一直在修改这个特定的指令一段时间,但实际上只是使用选项(github.com/RubaXa/Sortable)下作者代码中的 cmets,然后深入了解事件回调以查看传递的内容。很高兴能提供帮助。【参考方案2】:

查看自述文件,dnd-drop 事件会触发任何丢弃 - 无论它是否在同一个列表中。

按照您现在的脚本,您需要检查事件(或将一些附加信息传递到您的回调中)以确定事件触发的列表。

【讨论】:

【参考方案3】:

嗨,我添加了一个在 event.dataTransfer 中设置变量的 dragstartCallback 有关我拖动的 obj 的来源/来源的信息:

    $scope.dragstartCallback = function(event)
       var id  = event.target.id;
       var parent = $('#' + event.target.id).closest('ul')[0].id;
       var group = $('#' + event.target.id).closest('div')[0].id;

       event.dataTransfer.setData("id", id);
       event.dataTransfer.setData("parent", parent);
       event.dataTransfer.setData("group", group);
       return true;
    

在 dropCallback 中,我只检查是 List A 还是 List B

    $scope.dropCallback = function(event, index, item, external, type, allowedType) 
       $scope.logListEvent('dropped at', event, index, external, type);
       var idDivSource = event.dataTransfer.getData("parent");
       var idDivDestination = $(event.target).closest('ul')[0].id;

       var groupSource = event.dataTransfer.getData("group");
       var groupDestination = $('#' + event.target.id).closest('div')[0].id;

       if(groupSource == groupDestination)

          if(idDivSource != idDivDestination)
             if(idDivDestination == 'IDLISTB')
                return item?
             
             if(idDivDestination == 'IDLISTA')
                DO Something else
             
             DO Something else
          

        
    

html代码:

    <div class="associated-drag-and-drop DnD" id="GROUP-MyD&D1" ng-repeat="(listName, list) in models.lists" flex="">
       <ul dnd-list="list" id="listName" dnd-drop="dropCallback(event, index, item, external, type, 'containerType')" flex="">
          <md-list-item class="associated-list__item" ng-repeat="item in list | filter:searchFilter" id="item.id"
             dnd-dragover="dragoverCallback(event, index, external, type)"
             dnd-dragstart="dragstartCallback(event)"
             dnd-draggable="item"
             dnd-moved="list.splice($index, 1)"
             dnd-effect-allowed="move"
             dnd-selected="models.selected = item"
             ng-class="'selected': models.selected === item"
             class="noright associated-list__item"
             >
             CONTENT
          </md-list-item>
       </ul>
     </div>

不要使用这种类型的过滤器“| filter:searchFilter” 但是使用 ng-show="并把条件放在这里" 替代更改 dnd-moved="list.splice($index, 1)" 中对 $index 的引用

如果您不进行此更改,则拖放时过滤列表会出现问题

示例 未过滤列表 您将在 2 ng-repeat 中有 2 个数组

    ListA                             ListB
    index1 of     value               index2 of     value
    ng-repeat    of list              ng-repeat    of list
       0          aaa                    0          ppp
       1          bbb                    1          qqq
       2          ccc                    2          www
       3         dddaaa                  3         eeerrr
       4         eeeccc                  4         mmmwww
      ecc...                           ecc...

拖放列表对 ng-repeat 的索引起作用

过滤列表 现在,如果我们使用“| filter:searchFilter”代码为“a”制作过滤器 angular 会列出这个列表

     List A                         List B
      0      aaa
      1      dddaaa

拖动“dddaaa”时的索引将是 1 而不是 3 所以当它被放到 listB 中时,它不会从 listA 中删除 因为索引与非过滤列表不同

如果你使用 ng-show="condition" 它将保持列表的原始索引不被过滤

    <md-list-item ng-repeat="item in list"
        ng-show="condition">
    </md-list-item>

我的物品清单:

    $scope.models = 
       lists: 
          "LISTA": [1,2,3], 
          "LISTB": [1,2,3]
       
    ;

【讨论】:

以上是关于根据特定条件拖放列表的主要内容,如果未能解决你的问题,请参考以下文章

将根据特定条件调整(添加或删除)行的 Google 表格脚本

根据条件展平 R 中的列表

使用 Linq 根据条件过滤对象列表

Python根据条件拆分列表值

循环遍历记录集并根据条件将记录写入特定行

Access 2010:根据特定组合框条件过滤字段中包含多个值的报表