Reputation: 819
I have a list of items (students) in a mat-list component on the left side of my screen (general list). I also have a list of class-room Components on the right side of my screen. In each class-room Component, there is a mat-list of students.
I want to be able to drag students from to the general List to one of the students lists contained inside any of the class-room Component using the new Drag&Drop API of angular material
the pseudo code looks like this:
<mat-list #studentsList="cdkDropList" cdkDropList [cdkDropListData]="students">
<mat-list-item cdkDrag *ngFor="let student of studentes">
{{student.name}}
</mat-list-item>
</mat-list>
<div class="right-panel>
<app-class-room *ngFor="let cr of classRooms" [classRoom]="cr"></app-class-room>
</div>
Obviously, I can't use the [cdkDropListConnectedTo]
input on the general list as I don't have access to the student list inside the Class-room Component. How should I proceed?
Upvotes: 6
Views: 16657
Reputation: 531
I'd like to expand on the previous answers since I couldn't find working examples for my scenarios. Please mind that I simplified this example to stress the important bits (connecting the desired lists).
The "actual transfer logic" is realized by (cdkDropListDropped)="onDrop($event)"
.
There's a really basic example on that.
Sometimes we don't want to connect ALL child components, but only certain ones.
For that we will use cdkDropListConnectedTo
, BUT we will have to give every cdkDropList
a unique id. The catch is that it is NOT a usual HTML id.
<component1 id="component1" cdkDropList> // <- NO!
We would receive an error of this kind
CdkDropList could not find connected drop list with id component1
The documentation states thatcdkDropList
has a dedicated @Input()
attribute for id
.
Hence the right way to connect the lists:
<component1 [id]="'component1'" [cdkDropListConnectedTo]="'component2'" cdkDropList></...>
<component2 [id]="'component2'" cdkDropList></...>
<component3 [id]="'component3'" cdkDropList></...>
You can now ONLY drag from component1 to component2.
Please mind that the id
in this example is a string.
We have to wrap the string in ' '
to pass them to @Input()
(here's a little guide in case you're not familiar with it).
Adding cdkDropListGroup
to a parent element connects all child elements and allows dragging between them. cdkDropListGroup documentation.
<section cdkDropListGroup>
<component1 cdkDropList></component1>
<component2 cdkDropList></component2>
<component3 cdkDropList></component3>
</section>
Every item can be transferred between component 1, 2 and 3. working example of cdkDropListGroup Directive
Edit: Here's a working example with two components.
Upvotes: 6
Reputation: 106
You can also use CdkDropListGroup as a parent div, any child element will be a part of the group, no matter how many or where it is formed (ngFor, etc...), you can then place the div on an opposite side of the view with CSS. Helpful if you are dynamically creating DropLists en masse
Upvotes: 1
Reputation: 7713
You can use string instead of reference as mentionned in the API documentation :
@Input('cdkDropListConnectedTo') connectedTo: (CdkDropList | string)[] | CdkDropList | string
Other draggable containers that this container is connected to and into which the container's items can be transferred. Can either be references to other drop containers, or their unique IDs.
I made an example using a list of all dropable elements ids.
allDropLists = [ 'studentsList', ...this.classRooms
.map(_ => _.name)];
Which I pass to the ClassRoomComponent as an input :
<app-class-room
*ngFor="let classRoom of classRooms"
[classRoom]="classRoom" [allDropLists]="allDropLists">
The complete running example is here.
Upvotes: 3