Suppose I have two lists: a list of some products and a list of product categories. I would like to be able to move a product to a category by dropping it on a corresponding category list item. Here is the simple example:
<mat-list id="product-list" cdkDropList cdkDropListConnectedTo="category-list">
<mat-list-item *ngFor="let product of products" cdkDrag>
<span>product.name</span>
</mat-list-item>
</mat-list>
<mat-list id="category-list" cdkDropList (cdkDropListDropped)="onDrop($event)">
<mat-list-item *ngFor="let category of categories">
<span>category.name</span>
</mat-list-item>
</mat-list>
For now onDrop
handler is called but I don't know how to determine a category list item on which a product list item was dropped. Since category list items are not draggable currentIndex
is always zero in event.
Version of Angular/Angular Material is 12.1.3.
Finally I managed to solve this issue with elementFromPoint
function. Here is the updated example:
<mat-list id="product-list" cdkDropList>
<mat-list-item *ngFor="let product of products" cdkDrag
(cdkDragEnded)="onDragEnded($event, product)">
<span>product.name</span>
</mat-list-item>
</mat-list>
<mat-list id="category-list">
<mat-list-item *ngFor="let category of categories" class="drop-receiver"
(_drop)="onDrop($event, category)">
<span>category.name</span>
</mat-list-item>
</mat-list>
You can see that the lists are not connected anymore. Category list looks like an orginary one except its items have class drop-receiver
and listener of custom _drop
event.
In product list I listen cdkDragEnded
event. Here is the code of the event handler:
onDragEnded(event: CdkDragEnd, product: Product) {
const dropPointElement = document.elementFromPoint(event.dropPoint.x, event.dropPoint.y);
if (dropPointElement) {
const dropReceiver = dropPointElement.closest('.drop-receiver');
if (dropReceiver) {
const dropEvent = new CustomEvent('_drop', {detail: product});
dropReceiver.dispatchEvent(dropEvent);
}
}
}
In example above I look for a DOM element using drop point coordinates. Then if element is found I look for a closest DOM element with class drop-receiver
. Finally I send a custom event with name _drop
to a drop receiver element. Now in handler of that event it it possible to implement some logic of assigning category to the selected product.