如何为源和接收器下拉列表设置不同的 ckdDragPlaceholders?
Posted
技术标签:
【中文标题】如何为源和接收器下拉列表设置不同的 ckdDragPlaceholders?【英文标题】:How to have different ckdDragPlaceholders for the source and sink droplists? 【发布时间】:2020-09-25 04:08:25 【问题描述】:我正在使用 Angular 材质的 Drag and Drop 模块来移动一些元素。
更具体地说,我有多个cdkDropList
s,每个cdkDrag
:
<div *ngFor="let l of lists">
<div cdkDropList [cdkDropListConnectedTo]="all_lists">
<div cdkDrag>
content
</div>
</div>
</div>
每当我从列表中移动一个元素时,我都希望有一个占位符,例如:
<div cdkDrag>
content
<div *cdkDragPlaceholder>
placeholder content
</div>
</div>
但是,当我这样做时,占位符内容既显示在丢失的(当前被拖动的)元素(源列表)的位置,也显示在其新位置(接收器列表)的位置。我希望能够为接收器列表保留默认行为(显示根元素又名 content
),并且仅将占位符用于源列表。
我无法区分这两个地方,因为即使在“接收器”位置,它也是源元素的 html 正在显示(这有点道理,因为占位符是 cdkDrag
的属性而不是cdkDropList
)。
如何使用不同的占位符代替元素的原始位置和新位置?
Stackblitz example.
直觉:(多个)列表是一副牌,当将一张牌从 A 移动到 B 时,我在 A 牌中看到一张倒数第二(自定义占位符)牌,但是当我将鼠标悬停在 A 上时B 上的卡片,我看到那里的顶部 A 卡片。
【问题讨论】:
如果你能围绕这个创建一个堆栈闪电战就更好了。 类似的东西? stackblitz.com/edit/… 谢谢@David 举个例子。它朝着好的方向发展:我需要能够在两个方向上移动项目:所以,当我从下到上移动时,“自定义占位符”应该只显示在顶部(目前它不显示完全),而如果我从上到下移动,它应该只显示在底部(如当前所示)。我也不能以这种方式预先指定 csses,因为我不知道先验列表的数量 (div *ngFor="let l of lists"
)。
是的,我只做了 1 作为 poc 的一种方式,但它应该以相同的方式处理多个列表。你能根据你的要求创建一个包含多个列表的堆栈闪电战吗?
参见示例here。我试图以两种方式调整您的代码,但没有成功。
【参考方案1】:
如果我正确理解您的问题,您只想在拖动到另一个列表时显示自定义占位符,并在拖动到同一列表内时显示默认占位符。
要检测源列表之外的移动,您可以使用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;
模板:
<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>
如您所见,我创建了三个列表,使用cdkDragEntered
事件通过设置模板中使用的draggingOutsideSourceList
属性来确定拖动是在源列表的外部还是内部,以选择在占位符中显示的内容.
这里还有一个link to a fork of your StackBlitz,你可以看到它在工作。
【讨论】:
以上是关于如何为源和接收器下拉列表设置不同的 ckdDragPlaceholders?的主要内容,如果未能解决你的问题,请参考以下文章
如何为多个下拉菜单设置 jquery select2 的选定值?
在 Flutter 应用程序中单击时如何为下拉按钮中的项目设置填充