Angular Material 拖放 - 不同的对象类型

Angular Material Drag and Drop - Different Object Types

我正在构建一个购物车,我希望能够将产品列表中的项目拖放到购物车中,并将它们添加到购物车的 "items" 中。产品更像是技术服务,因此我不想使用术语服务...所以您会在模型中看到 "hours"。

我能够呈现这两个列表,并将产品拖放到购物车中。当然,购物车包含 CartItems,其中包含产品的 "snapshot"。显然这不能按预期工作。

我的问题是:如何使用拖放来完成此操作?

我也认识到我对这个问题的整个处理方法可能是错误的。我愿意接受任何建议。

而不是 post 一堆屏幕截图和代码,这里是应用程序的 link :) 在 Stackblitz 上:

编辑:这个 stackblitz 运行正常

drag-drop-test

型号如下:

export class Cart {
    id: string;
    title: string;
    items?: CartItem[];
}
export class CartItem {
    qty: number;
    hours: number;
    product: Product;
}
export class Product {
    id: string;
    title: string;
    dhours: number; // default hours
}

您需要先将 product 转换为 cartItem,然后再将其移动到其他数组。

const cartItem = [{
    qty: null,
    hours: null,
    product: event.previousContainer.data[event.previousIndex]
}]
transferArrayItem<CartItem>(cartItem,
    event.container.data,
    event.previousIndex,
    event.currentIndex);
event.previousContainer.data.splice(event.previousIndex, 1); // You will have to remove previous item yourself

更新 stackblitz https://stackblitz.com/edit/github-4t79ak 我只是为了从产品列表移动到购物车项目,你可以尝试其他方向。

cdk 拖放并不神奇。它使以可视化方式轻松管理两个对象 (*) 数组。但仅此而已:您有两个数组显示在 *ngFor 中,并且您更改(或不更改)拖动元素的数组。完成拖放后,Angular 重新绘制两个 *ngFors

如果您查看 event cdkDrapDrop,您会发现它具有如下属性(以及其他属性):

  1. 容器:放置物品的容器。 (container.data 是与 中的 cdkDropList 关联的数组,该项目已被删除)
  2. currentIndex:项目的当前索引。
  3. previousContainer:从中拾取项目的容器。 (previousContainer.data 是与 中的 cdkDropList 关联的数组,该项目已被拾取)
  4. previousIndex: 物品被拾取时的索引

不一定要用函数transferArrayItems,你可以用,例如

drop(event: CdkDragDrop<any>) {
    //get the data asociated to the item dragged
    const dragItem=previousContainer[previousIndex]
    //create an object using this data
    const addItem={id: dragItem.id,
                   title: dragItem.id,
                   dhours: dragItem.dhours,
    //add to the array of the data where we dropped the object
    container.data.splice(1, 0, addItem);
}

并保持与 中的 cdkDropList 关联的数组数组未被拾取。删除对象后,Angular 用数组

的数据重新绘制两个 "list"

(*)更新: 好吧,我实际上是在谈论数组作为 [cdkDropListData],但没有人禁止我们说数据是一个简单的字符串或一个简单的对象。有的喜欢

<div cdkDropList [cdkDropListData]="{name:'Name'}"
            [cdkDropListConnectedTo]="[cdkBoard]" 
            (cdkDropListDropped)="drop($event)" 
            cdkDropListSortingDisabled="true">
    <div cdkDrag>
         Drag me!
         <div *cdkDragPlaceholder></div>
    </div>
</div>

使得在放置事件中 previousContainer.data 是对象 {name:'Name'}