我目前正在开发一个 Angular 项目,我需要使用 PrimeNG 的 Carousel 组件以及 Angular Material 的拖放功能。单独来看,两个组件都按预期工作。但是,当我尝试组合它们时,拖放功能在轮播中停止工作。当我尝试删除项目时,控制台中没有错误。
当您将任务 1 从“待办事项”放入“完成”容器时,会发生错误。任务 1 仍然在“待办事项”中可见。
我做错了什么?
任务状态.component.html
<div class="task-status-container">
<div class="title-container">
<div class="title">{{ taskStatus.value }}</div>
</div>
<div
cdkDropList
[id]="taskStatus.key"
[cdkDropListData]="assignTasksByStatus(taskStatus)"
(cdkDropListDropped)="drop($event)"
class="task-status-drop-list"
>
@if(getTaskCount(taskStatus) === 0) {
<div class="no-task-container">
<div>No Tasks</div>
</div>
}
<p-carousel
[value]="assignTasksByStatus(taskStatus)"
[numVisible]="1"
[numScroll]="1"
[circular]="true"
>
<ng-template let-task pTemplate="item">
<div class="border-1 surface-border border-round m-2 p-3">
<div class="mb-3">
<div class="relative mx-auto">
<app-task cdkDrag [cdkDragData]="task" [task]="task"></app-task>
</div>
</div>
</div>
</ng-template>
</p-carousel>
</div>
</div>
以下是更改列表。
我们必须向 cdk 拖放提供输入
[cdkDropListConnectedTo]
,以便它知道它连接到哪些其他拖放模块。在这里,我们通过输入在根组件中准备的 ID 数组并作为
@Input` 来指定这一点
我们可以使用dnd列表的模板引用
#list="cdkDropList"
代替函数,然后使用它来访问数据属性,即列表,而不是使用单独的函数。由于操纵发生在 DND 级别,因此我们应该在其他位置使用相同的参考。
使用
moveItemInArray
或transferArrayItem
更新列表后,我们需要创建一个新的引用,否则轮播无法检测到更改,为此我们可以使用数组解构来刷新轮播
<div class="task-status-container">
<div class="title-container">
<div class="title">{{ taskStatus.value }}</div>
</div>
<div
#list="cdkDropList"
cdkDropList
[id]="taskStatus.key"
[cdkDropListData]="assignTasksByStatus(taskStatus)"
(cdkDropListDropped)="drop($event)"
[cdkDropListConnectedTo]="taskStatusKeys"
class="task-status-drop-list"
>
<!-- 1-->
@if(list.data.length=== 0) {
<!-- 2 -->
<div class="no-task-container">
<div>No Tasks</div>
</div>
}
<!-- 2 -->
<p-carousel
[value]="list.data"
[numVisible]="1"
[numScroll]="1"
[circular]="true"
>
<ng-template let-task pTemplate="item">
<div class="border-1 surface-border border-round m-2 p-3">
<div class="mb-3">
<div class="relative mx-auto">
<app-task cdkDrag [cdkDragData]="task" [task]="task"></app-task>
</div>
</div>
</div>
</ng-template>
</p-carousel>
</div>
</div>
import {
CdkDragDrop,
moveItemInArray,
transferArrayItem,
CdkDropList,
CdkDrag,
} from '@angular/cdk/drag-drop';
import { Component, Input, ViewChild } from '@angular/core';
import { Subscription } from 'rxjs';
import { TaskComponent } from './task/task.component';
import { TASK_STATUSES } from '../../../task-constants';
import { TaskStatus } from '../../../status';
import { Task } from '../../../task';
import { CarouselModule } from 'primeng/carousel';
@Component({
selector: 'app-task-status',
standalone: true,
imports: [TaskComponent, CdkDropList, CdkDrag, CarouselModule],
templateUrl: './task-status.component.html',
styleUrl: './task-status.component.scss',
})
export class TaskStatusComponent {
@ViewChild(CdkDropList) list!: CdkDropList;
protected readonly TASK_STATUSES = TASK_STATUSES;
@Input() taskStatus!: TaskStatus;
@Input() taskStatusKeys!: Array<string>; //<-1
tasksSubscription!: Subscription;
tasks: Task[] = [
{ id: 1, title: 'Task 1', status: TASK_STATUSES['TO_DO'] },
{ id: 2, title: 'Task 2', status: TASK_STATUSES['DONE'] },
{ id: 3, title: 'Task 3', status: TASK_STATUSES['DONE'] },
];
tasksByStatus!: { [key: string]: Task[] };
ngOnInit() {
this.tasksByStatus = Object.keys(TASK_STATUSES).reduce((acc, cur) => {
acc[cur] = this.tasks.filter((x) => x.status.key === cur);
return acc;
}, {} as { [key: string]: Task[] });
}
drop(event: CdkDragDrop<Task[]>) {
if (event.previousContainer === event.container) {
moveItemInArray(
event.container.data,
event.previousIndex,
event.currentIndex
);
} else {
transferArrayItem(
event.previousContainer.data,
event.container.data,
event.previousIndex,
event.currentIndex
);
}
event.previousContainer.data = [...event.previousContainer.data]; // <= 3
event.container.data = [...event.container.data]; // <= 3
}
public assignTasksByStatus(status: TaskStatus): Task[] {
return this.tasksByStatus[status.key];
}
public getTaskCount(status: TaskStatus): number {
return this.tasksByStatus[status.key]?.length || 0;
}
}
<div cdkDropListGroup class="task-status-list-container">
@for (taskStatus of Object.values(TASK_STATUSES); track taskStatus.key) {
<app-task-status
[taskStatus]="taskStatus"
[taskStatusKeys]="taskStatusKeys"
></app-task-status>
<!-- 1-->
}
</div>
import { Component } from '@angular/core';
import { TaskStatusComponent } from './task-status/task-status.component';
import { TASK_STATUSES } from '../../task-constants';
import { CdkDropListGroup } from '@angular/cdk/drag-drop';
@Component({
selector: 'app-task-status-list',
standalone: true,
imports: [TaskStatusComponent, CdkDropListGroup],
templateUrl: './task-status-list.component.html',
styleUrl: './task-status-list.component.scss',
})
export class TaskStatusListComponent {
protected readonly TASK_STATUSES = TASK_STATUSES;
public readonly taskStatusKeys = Object.values(TASK_STATUSES).map(
//<-1
(x: any) => x.key //<-1
); //<-1
protected readonly Object = Object;
}