限制 angular 中两个不可拖动项之间的拖放

restricting drag and drop between two non-dragable items in angular

我正在制作一个 angular 应用程序,其中有两个列表。从列表 'A',我可以一次又一次地 复制 项目到列表 'B'。问题是,我想让拖动的项目只添加到列表 'B' 中的开始和结束项目之间。 see image

这是我目前尝试过的方法:

HTML:

        <mat-drawer-container class="example-container">
            <mat-drawer mode="side" opened>
                <h3>Create your Workflow</h3>
                <h5>Drag and drop the elements to visualize the process.</h5>
                <div cdkDropList
                #optionsList="cdkDropList"
                [cdkDropListData]="options"
                [cdkDropListConnectedTo]="[workflowList]"
                class="example-list"
                cdkDropListSortingDisabled
                (cdkDropListDropped)="drop($event)"
                [cdkDropListEnterPredicate]="noReturnPredicate">
                <div class="example-box" cdkDrag *ngFor="let item of options"> {{item}} </div>
            </div>
            </mat-drawer>
            <mat-drawer-content>
                <div cdkDropList
                    #workflowList="cdkDropList"
                    [cdkDropListData]="workflow"
                    [cdkDropListConnectedTo]="[optionsList]"
                    class="example-list"
                    (cdkDropListDropped)="drop($event)"
                    [cdkDropListSortPredicate]="sortPredicate"
                    >
                    <div class="example-box"  [cdkDragDisabled]="item.disabled" *ngFor="let item of workflow" cdkDragLockAxis="y" cdkDrag>{{item.value}}</div>
                </div>
            </mat-drawer-content>

.ts -> 导出 class:

options = [
    'Step',
    'Branch' 
  ];

  workflow=[
      {value: 'Start', disabled: true},
      {value: 'Finish', disabled: true}
    ];


  drop(event: any) {
    if (event.previousContainer === event.container) {
      moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
    } else {
      copyArrayItem(
        event.previousContainer.data,
        event.container.data,
        event.previousIndex,
        event.currentIndex
      );
    }  
  }

  noReturnPredicate(){
    return false;
  }

  sortPredicate(){
    return false;
  }

现在我只能在工作流程中输入'End'之后的选项。我希望它在开始和结束之间。有人可以帮忙吗?

另外,添加的列表中没有显示选项名称,如果有人能在这方面指导我,那将非常有帮助。谢谢

我在 drop 方法中使用了如下条件:

event.currentIndex>0 && event.currentIndex<this.workflow.length

有两个问题:

  1. 两个下拉列表应具有相同的值类型。你有:

    options: string[],
    workflow: {value: string, disabled: boolean}[],
    

    所以,你应该统一类型(或者写你自己的 copyArrayItem 方法来在类型之间转换):

    interface DragItem {
      value: string;
      disabled: boolean;
    }
    ...
    
      options: DragItem[] = [
        { value: 'Step', disabled: ... },
        { value: 'Branch', disabled: ... }
      ];
    
      workflow: DragItem[] = [
        { value: 'Start', disabled: true },
        { value: 'Finish', disabled: true }
      ];
    
  2. 如果你想让索引保持在定义的范围内,检查它:

    sortPredicate(index: number, drag: CdkDrag, drop: CdkDropList): boolean {
      // preliminary check, not reliable
      return index > 0 && index < drop.getSortedItems().length;
    }
    

    sortPredicate 实际上是不可靠的(我可以将项目放置在禁止位置),你应该仔细检查 drop 事件中的索引行为并修复它:

    drop(event: CdkDragDrop<DragItem[], any>) {
      if (event.previousContainer === event.container) {
        moveItemInArray(
          event.container.data,
          event.previousIndex,
          event.currentIndex
        );
      } else {
        let currentIndex = event.currentIndex;
    
        // double check index range
        if (0 === currentIndex) {
          currentIndex++;
        }
        if (event.container.getSortedItems().length === currentIndex) {
          currentIndex--;
        }
    
        copyArrayItem(
          event.previousContainer.data,
          event.container.data,
          event.previousIndex,
          currentIndex
        );
      }
    }
    

工作示例:https://stackblitz.com/edit/angular-drag-drop-range