Angular Перетаскивание материала - различные типы объектов - PullRequest
2 голосов
/ 27 января 2020

Я создаю корзину для покупок и хотел бы иметь возможность перетаскивать элементы из списка продуктов в корзину и добавлять их в «элементы» корзины. Продукты больше похожи на технические услуги, поэтому я не хотел использовать термин «Услуги» ... поэтому в моделях вы увидите «часы».

Я могу отобразить два списка, и перетащите Продукты в Корзину ... но, конечно, Корзина содержит элементы CartItems, которые содержат "снимок" Продукта. Очевидно, что это не работает должным образом.

Мой вопрос: как я могу сделать это с помощью перетаскивания?

Я также признаю, что весь мой подход к этой проблеме может быть неправильным. Я открыт для любых рекомендаций.

Вместо того, чтобы публиковать скриншоты и код, вот ссылка на приложение :) на Stackblitz:

РЕДАКТИРОВАТЬ: Этот стекблиц работает правильно

тест перетаскивания

Модели представлены следующим образом:

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
}

Ответы [ 2 ]

1 голос
/ 28 января 2020

cdkdrag и drop это не волхвы c. это позволяет легко управлять двумя массивами объекта (*) визуально. но это только так: у вас есть два массива, которые отображаются в * ngFor, и вы изменяете массивы (или нет), перетаскивая элементы. После завершения перетаскивания Angular перекрасим два * ngFors

Если вы посмотрите на событие 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 перерисовали два «списка» с данными массивов

(*) Обновлено: Ну, действительно, я говорил о массиве как [cdkDropListData] , но никто не запрещает нам, чтобы данные были простой строкой или простым объектом. Например,

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

указывает, что в событии drop предыдущийContainer.data был объектом {name: 'Name'}

1 голос
/ 27 января 2020

Вам нужно будет преобразовать 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 Я сделал только для перехода из списка продуктов в корзину, вы можете попробовать ее в другом направлении.

...