角度材质中的拖放功能在 PrimeNG 轮播中不起作用

问题描述 投票:0回答:1

我目前正在开发一个 Angular 项目,我需要使用 PrimeNG 的 Carousel 组件以及 Angular Material 的拖放功能。单独来看,两个组件都按预期工作。但是,当我尝试组合它们时,拖放功能在轮播中停止工作。当我尝试删除项目时,控制台中没有错误。

当您将任务 1 从“待办事项”放入“完成”容器时,会发生错误。任务 1 仍然在“待办事项”中可见。

我做错了什么?

演示@StackBlitz

任务状态.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>
angular angular-material carousel primeng angular-cdk-drag-drop
1个回答
0
投票

以下是更改列表。

  1. 我们必须向 cdk 拖放提供输入

    [cdkDropListConnectedTo]
    ,以便它知道它连接到哪些其他拖放模块。在这里,我们通过输入在根组件中准备的 ID 数组并作为
     
    @Input`

    来指定这一点
  2. 我们可以使用dnd列表的模板引用

    #list="cdkDropList"
    代替函数,然后使用它来访问数据属性,即列表,而不是使用单独的函数。由于操纵发生在 DND 级别,因此我们应该在其他位置使用相同的参考。

  3. 使用

    moveItemInArray
    transferArrayItem
    更新列表后,我们需要创建一个新的引用,否则轮播无法检测到更改,为此我们可以使用数组解构来刷新轮播

完整代码:

任务状态 HTML:

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

任务状态T:

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

任务列表HMTL

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

任务状态TS:

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

Stackblitz 演示

© www.soinside.com 2019 - 2024. All rights reserved.