【问题标题】:angular CDK drag & drop: nested droplist角CDK拖放:嵌套下拉列表
【发布时间】:2020-02-18 13:01:34
【问题描述】:

我正在尝试建立一个demo app,我可以在其中规划学生和他们的课桌。当一个教室有太多课桌时,我可以把它们放在另一个教室里。然后,我可以在所述课桌上计划学生。我使用cdkDropListGroup,因为教室的数量是动态的。

当我将一张有学生的课桌放在“未分配”学生列表中时,课桌仍保留在教室中,但学生按预期放入列表中。 但是,当我尝试将学生放在桌子上时,只允许将产品放在列表中的谓词不允许它们。但是,当我删除谓词时,学生会被丢弃在教室列表而不是课桌中......

与学生一起放下课桌可以正常工作:

将学生放到课桌上失败:

我需要帮助将学生专门放在桌子上而不是教室里,从而触发 dropStudent。

我认为将桌子的容器提高到更高的 Z-Index 可能会有所帮助,但这没有用。

参考:

【问题讨论】:

  • 您可以使用cdkDropListConnectedTo 属性,例如[cdkDropListConnectedTo]="[unassignedStudents]"

标签: angular angular-material


【解决方案1】:

您需要在未分配的学生列表上使用cdkDropListConnectedTo 选项,并添加课桌列表的所有实例。这是因为 CdkDropListGroup 只查看兄弟列表,而不查看子列表:

你需要在你的桌面下拉列表中添加一个模板引用,这样你就可以在你的组件 ts 中查询这个,或者你可以使用一串 ID。我认为模板引用更通用,但为了举例,我将使用 id:

<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>

如您所见,cdkDropListConnectedTo 绑定了desks。在您的组件中,您可以像这样定义办公桌:

desks: string[] = [];

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

要使其与ViewChildren 一起使用,您需要在ngAfterViewInit 中添加类似的内容:

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

working example

【讨论】:

  • 感谢您提供快速、完整的答案,并附有工作示例和解释!我不知道我可以将 String[] 分配给cdkDropListConnectedTo
  • 似乎在我移动一张桌子后,我不能再将学生放到那个特定的桌子上。当我添加`this.desks = this.deskLists.toArray(); this.cd.markForCheck(); this.cd.detectChanges();` 到dropStudent,将一个学生放在另一张桌子上后它会起作用
  • @JamesD 对,我注意到字符串 id 列表不再起作用,因此链接中的“工作示例”实际上使用了带有 ViewChildren 的桌面列表。无论如何,这是最好的选择:)/ O
  • @JamesD 我已经用更好的方法更新了我的答案来处理列表中的更改。这将确保办公桌得到更新。您也可以将其用作无需订阅的可观察对象,并在模板中使用 async 管道
  • @JamesD 不客气。它需要startWith(true),否则在加载组件时它不会被触发,仅供参考:D
猜你喜欢
  • 2021-01-14
  • 2019-06-08
  • 1970-01-01
  • 2019-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-24
相关资源
最近更新 更多