根据特定条件拖放列表

时间:2015-07-20 06:27:26

标签: javascript jquery angularjs drag-and-drop

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

  1. 将项目从列表A拖到列表B
  2. 将项目从列表B拖到列表A
  3. 重新排列列表A中的项目
  4. 重新排列列表B中的项目
  5. 使用库网站上的一个简单示例(http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/simple)我可以看到这四个条件很容易实现。然而,当我想引入稍微复杂的行为时,事情开始变得毛茸茸:

    1. 将项目从列表A拖到列表B时,我想要发生一些事情(使用dnd-drop回调很容易实现。目前适用于我
    2. 当将列表B中的项目拖动到列表A时,除了常规删除之外,我不希望发生任何事情(即项目在列表A中结束并且没有任何奇特的事情发生)。 目前适用于我
    3. 当重新排序列表A中的项目时,当项目被重新放入列表中的新位置时(即使它被放回到原始位置),也不会发生任何事情。这是我遇到问题的地方 - 请参阅以下内容以获得进一步说明
    4. 当重新排序列表B中的项目时,当项目被重新放入列表中的新位置时(即使它被放回到其原始位置),也不会发生任何事情。 目前适用于我
    5. 我在很大程度上调整上面提供的示例链接中使用的示例代码。我遇到的问题是当我将列表A中的项目重新排序时,我想要将列表A中的项目移动到列表B时发生的操作。

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

      我的名单:

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

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

      谢谢!

3 个答案:

答案 0 :(得分:1)

查看README,dnd-drop事件将触发任何丢弃 - 无论它是否在同一列表中。

现在按照脚本进行操作,您需要检查事件(或将一些其他信息传递给回调)以确定事件触发的列表。

答案 1 :(得分:1)

如果你没有完全致力于那个图书馆(顺便说一句,不能使用触摸屏),RubaXa的Sortable就是真相:Sortable

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

答案 2 :(得分:0)

您好我添加了一个在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中我只检查是列表A还是列表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}]
       }
    };