Reputation: 290
I am currently using Angular 2 and a drag and drop module from https://material.angular.io/cdk/drag-drop/overview. I have made the drag and drop features work. I have two different types of class objects that i desire to be limited to their own types of drag and drop lists.
This could very likely be solved with grouping the lists but since I am using recursion other issues came up...
Currently I am having every lists inside the same group, meaning that anything can be dragged and dropped in every list (cdkDropListGroup, is positioned in a component before the recursion part is performed).
I am trying to make the lists restricted to only accept either Element or Attribute (but not both), but I have no idea of how to do this...
I have the following:
Classes:
export class Attribute {
name: string;
type: string;
}
export class Element {
id: number;
name: string;
elements: Element[]
attributes: Attribute[];
}
HTML:
<div >
Elements
<div
cdkDropList
[cdkDropListData]="elements"
class="example-list"
(cdkDropListDropped)="drop($event)"
[cdkDropListEnterPredicate]="isElement">
<div type="button" text-align="right" class="btn btnNotInline" (click)="addNewElement()">
<img src="assets/img/IconPlus.png" class="elementListIcon"></div>
<div *ngFor="let element of elements" class="example-box" cdkDrag>
<mat-list>
<mat-list-item>
<mat-form-field appearance="standard dense" class="example-container">
<input matInput placeholder="{{element.name}}">
</mat-form-field>
</mat-list-item>
<mat-list-item>
<div
cdkDropList
[cdkDropListData]="attributes"
class="cdk-drag-list-attributes"
(cdkDropListDropped)="drop($event)"
[cdkDropListEnterPredicate]="isAttribute">
<div type="button" text-align="right" class="btn btnNotInline" (click)="addNewAttribute()">
<img src="assets/img/IconPlusPurple.png" class="elementListIcon"></div>
<div *ngFor="let attribute of attributes" class="example-container" cdkDrag>
<p class="mat-input-element-attribute">
<input matInput placeholder="{{attribute.name}}">
<input matInput placeholder="{{attribute.type}}">
</p>
</div>
</div>
</mat-list-item>
<mat-list-item>
<app-listboardelement [attributes]="element.attributes" [elements]="element.elements"></app-listboardelement>
</mat-list-item>
</mat-list>
</div>
The ts. method being called (the attribute looks alike)
isElement(drag : CdkDrag){
console.log("check " + (drag instanceof Element) + typeof drag + " , "+ typeof drag.data + ", "+ drag.data + " , " +(drag.data instanceof Element));
return (drag.data instanceof Element);
}
from the output I simply gets: "check false object , undefined, undefined , false" From this I have tried to compare the dragged object with a class.. but I didn't have any luck.
Is there any way I can limit dragged object to certain lists dynamically? I know about [cdkDropListConnectedTo] but this gave me issues with the occuring recursion and the bindings. Any guidance would be appreciated
EDIT:
Added image for presentation of how it is displayed - but does not work properly;
Upvotes: 5
Views: 11175
Reputation: 1198
The ts. method being called (the attribute looks alike)
isElement(drag : CdkDrag){ console.log("check " + (drag instanceof Element) + typeof drag + " , "+ typeof drag.data + ", "+ drag.data + " , " +(drag.data instanceof Element)); return (drag.data instanceof Element); }
drag.data
does not work, because you didn't assign any data to your cdkDrag
via [cdkDragData]
<div *ngFor="let element of elements" class="example-box" cdkDrag [cdkDragData]="element">
...
</div>
To your question... You can either create two sets of cdkDropList
arrays for elements and attributes and connect the list groups with the [cdkDropListConnectedTo]
binding or connect all lists together in one array and allow the drop with the [cdkDropListEnterPredicate]="isElement"
you already mentioned.
To solve the problem regarding recursion, you need to do some additional steps and check if the current drop container is the right one.
I've a detailed description in my question regarding nesting.
Angular Nested Drag and Drop / CDK Material cdkDropListGroup cdkDropList nested
Upvotes: 0
Reputation: 417
You can always check the drag-n-drop 'origin to destination' containers and take action accordingly, something like :
drop(event: CdkDragDrop<string[]>) {
// same container (just reorder items)
if (event.previousContainer === event.container) {
moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
} else {
// from first list to second list
if (event.previousContainer.id === 'cdk-drop-list-0' && event.container.id === 'cdk-drop-list-1') {
// do something
}
// from second list to first list
if (event.previousContainer.id === 'cdk-drop-list-1' && event.container.id === 'cdk-drop-list-0') {
// do something
}
}
}
Hope this helps!
Upvotes: 0