Цель: создать таблицу с использованием материала Angular, который можно изменить с помощью Angular Drag & Drop.

Ожидаемое поведение : при перетаскивании следует изменить порядок таблицы

Текущее поведение : строки можно перетаскивать, и порядок базового источника данных изменяется, но когда строка отбрасывается, она возвращается в исходное положение в таблице.

Смотрите вот этот пример:

https://stackblitz.com/edit/drag-drop-reorder-mattable

Как это можно исправить / реализовать?

(Кроме того, я не уверен, почему он так плохо оформлен в Stackblitz. Любое понимание там также будет оценено)

Изменить: я нашел супер-хакерский способ заставить строки снова отображаться в правильном порядке, но нет никакого способа, которым он должен был быть реализован. Я просто поставил t.renderRows() на выполнение после обработчика события drop. См. Полную строку ниже

<mat-table #t
  cdkDropList
  (cdkDropListDropped)="onListDrop($event); t.renderRows()" 
  [dataSource]="dataSource"
  class="mat-elevation-z8">
  ...
</mat-table>

ИЗМЕНИТЬ 2: Я провел простой рефакторинг для использования rxjs, и первое изменение порядка перетаскивания для каждого элемента отлично работает. Но когда я пытаюсь переместить элемент, который уже был перемещен один раз, я не получаю ожидаемого поведения. Приложение Stackblitz обновлено.

1
Trevor 10 Янв 2019 в 10:06

2 ответа

Лучший ответ

Вы столкнулись с проблемой angular / material2 № 14056 "cdkDropList: event.previousIndex не обновляется на втором ходу ». Обходной путь глубокого клонирования источника данных подробно описан в проблеме и комментариях.

Взгляните здесь, где я поиграю с вашей демонстрацией после небольшого изменения в журнале консоли (console.log(`Moving item[${event.previousIndex}] "${this.items[event.previousIndex]}" to index ${event.currentIndex}`) )

Я перетаскиваю «Элемент 0» из индекса 0 в индекс 3. Элемент с индексом 0 перемещается в индекс 3. ✔️
Я перетаскиваю «Элемент 0» из индекса 3 в индекс 1. Элемент с индексом 0 перемещается в индекс 1. ✖️
Я перетаскиваю «Элемент 0» из индекса 3 в индекс 2. Элемент с индексом 0 перемещается в индекс 2. ✖️

event.previousIndex по ошибке остается неизменным для строки после того, как она была перемещена в другой индекс.

3
Lezardo 16 Янв 2019 в 05:32

Как вы упомянули при редактировании, вам нужно вызывать renderRows() каждый раз, когда вы изменяете источник данных. Он даже упоминается в документации по Angular Material здесь.

Отображает строки на основе последнего набора данных таблицы, которые были либо предоставлены непосредственно в качестве входных данных, либо получены через поток Observable (напрямую или из DataSource). Проверяет различия в данных с момента последнего сравнения, чтобы выполнить только необходимые изменения (добавить / удалить / переместить строки).

Если источником данных таблицы является DataSource или Observable, это будет вызывается автоматически каждый раз, когда предоставленный поток Observable испускает новый массив данных. В противном случае, если ваши данные представляют собой массив, эта функция будет необходимо вызвать для обработки любых изменений.

Что вы можете сделать, чтобы каждый раз вызывать renderRows(), так это преобразовать ваш источник данных в Observable и выдать новое значение в вашей функции onListDrop(), чтобы таблица обновлялась автоматически каждый раз, когда вы перетаскиваете строку ,

2
Fabian Küng 10 Янв 2019 в 09:40