简体   繁体   中英

angular CDK drag & drop: nested droplist

I'm trying to build a demo app where I can plan students and their desks. When a classroom has too many desks I can put them in another classroom. I can then plan the students on said desks. I'm using cdkDropListGroup because the amount of classrooms is a dynamic.

When I drop a desk with students on the 'not assigned' student list, the desk remains in the class room, but the students drop into the list as expected. However when I try to drop the students on the desks, the predicate, which only allows products to be dropped in the list, doesn't allow them. When I remove the predicate however, the student are dropped in the classrooms list instead of the desks...

Dropping desks with students works properly:

应用程序的正常运行

Dropping students on desks fails:

不合格部分

I need help with dropping the students specifically on the desks instead of the classrooms, causing dropStudent to trigger.

I thought raising the container for the desks to a higher Z-Index might help but that didn't work.

references:

You need to use the cdkDropListConnectedTo option on the not assigned students lists, and add all instances of the desk lists. That's beacuse the CdkDropListGroup only looks at sibling lists, not at children:

You need to add a template reference to your desk droplist, so you can query this in your component ts, or you can use the a string of IDs. I think the template reference is more versatile, but for the sake of example I'll use the ids:

<div cdkDropList 
      id="{{studentList.listName}}" 
      [cdkDropListData]="studentList.student"
      class="example-list"
      (cdkDropListDropped)="returnStudent($event)"
      [cdkDropListEnterPredicate]="userReturnPredicate"
      [cdkDropListConnectedTo]="desks">
  <div  *ngFor="let person of studentList.student"
        class="example-box" 
        cdkDrag
        [cdkDragData]="person">
    {{person.userName}}
  </div>
</div>

As you can see the cdkDropListConnectedTo has desks binded. In your component you can define desks like this:

desks: string[] = [];

this.desks = this.projectLists.map(
  (list) => list.products.map((product) => product.productName)
).flat(2);

To make it work with ViewChildren , you need something like this in your ngAfterViewInit :

ngAfterViewInit(): void {
  this.deskLists.changes.pipe(
    startWith(true),
    tap(() => {
      this.desks = this.deskLists.toArray();
      this.cd.markForCheck();
      this.cd.detectChanges();
    }),
  ).subscribe();
}

working example

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM