如何为源和接收器下拉列表设置不同的 ckdDragPlaceholder?

syg*_*ygi 4 drag-and-drop angular-material angular-material2 angular

我正在使用 Angular 材料的拖放模块来移动一些元素。

更具体地说,我有多个cdkDropLists,cdkDrag每个都有一个:

<div *ngFor="let l of lists">
  <div cdkDropList [cdkDropListConnectedTo]="all_lists">
    <div cdkDrag>
      content
    </div>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

每当我从列表中移动元素时,我希望有一个占位符,例如:

 <div cdkDrag>
      content
      <div *cdkDragPlaceholder>
          placeholder content
      </div>
 </div>
Run Code Online (Sandbox Code Playgroud)

但是,当我执行此操作时,会显示占位符内容,以代替丢失(当前正在拖动)的元素(源列表)以及其新位置(接收器列表)。我希望能够保留content接收器列表的默认行为(显示根元素又名),并仅使用源列表的占位符。

不过,我无法区分这两个位置,因为即使在“接收器”位置,也显示了源元素的 HTML(这有点道理,因为占位符是 a 的属性,cdkDrag而不是cdkDropList)。

如何使用不同的占位符来代替元素的原始位置和新位置?

堆栈闪电战示例

直觉:(多个)列表是一副牌,当将一张牌从 A 移动到 B 时,我在 A 牌组中看到一张倒数第二张(自定义占位符)牌,但是当我将顶部 A 卡悬停在 B 上时,我看到上面的 A 卡。

Ale*_*esD 5

如果我正确理解您的问题,您只想在拖动到另一个列表时显示自定义占位符,并在拖动同一列表时显示默认占位符。

要检测源列表外的移动,您可以使用cdkDragEntered每当将项目从外部拖动到列表内时就会触发的事件。在CdkDragEnter事件数据中,您拥有输入的列表信息以及有关被拖动项目的所有信息。该项目包含其当前所属列表的信息。这意味着当我们输入的列表与项目列表不同时,已经输入了另一个列表。获得此信息后,您可以根据此信息更改占位符内显示的内容。

我已将您的 StackBlitz 示例更改为这种方法。

组件代码:

export class CdkDragDropConnectedSortingGroupExample {
  todo = [
    'Get to work',
    'Pick up groceries',
    'Go home',
    'Fall asleep'
  ];

  done = [
    'Get up',
    'Brush teeth',
    'Take a shower',
  ];

  another = [
    'Check e-mail',
    'Walk dog'
  ]

  lists = [this.todo, this.done, this.another];

  public draggingOutsideSourceList: boolean = false;

  drop(event: CdkDragDrop<string[]>) {
    if (event.previousContainer === event.container) {
      moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
    } else {
      transferArrayItem(event.previousContainer.data,
                        event.container.data,
                        event.previousIndex,
                        event.currentIndex);
    }
    this.draggingOutsideSourceList = false; // always reset after drag drop finishes
  }

  onCdkDragEntered(event: CdkDragEnter<string>) {
    this.draggingOutsideSourceList = event.container !== event.item.dropContainer;
  }
}
Run Code Online (Sandbox Code Playgroud)

模板:

<div cdkDropListGroup>
    <div class="example-container todoList" *ngFor="let list of lists">
        <div cdkDropList [cdkDropListData]="list" class="example-list" (cdkDropListDropped)="drop($event)">

            <div cdkDrag *ngFor="let item of list" (cdkDragEntered)="onCdkDragEntered($event)">
                <ng-template #itemTpl>
                    <div class="example-box">{{item}}</div>
                </ng-template>
                <div *cdkDragPlaceholder>
                    <div *ngIf="draggingOutsideSourceList; else itemTpl" class="customPlaceHolder">
                        Custom placeholder content only in sink list
                    </div>
                </div>
                <ng-container *ngTemplateOutlet="itemTpl"></ng-container>
            </div>
        </div>
    </div>
</div>
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我创建了三个列表,通过设置模板中使用的属性来选择在占位符中显示的内容,使用cdkDragEntered事件来确定拖动是在源列表外部还是内部。draggingOutsideSourceList

这里还有一个 StackBlitz 分支的链接,你可以在其中看到它的工作情况。