CDK Drag Drop некорректно меняет положение изображений

Я создал галерею изображений и намереваюсь изменить положение между ними. Для этого я использую библиотеку Drag & Drop cdk.

Моя проблема в том, что обмен изображениями не всегда происходит правильно, иногда я обмениваю первое изображение на второе, и этого обмена не происходит.

Как я могу сделать это полностью функциональным, как по горизонтали, так и по вертикали?

Есть ли способ, которым перетаскивание может запускаться только в том случае, если изображение хранится в mdc-image-list - with-text-protection class?

Спасибо !

ДЕМО

.HTML

  <ul class="mdc-image-list my-image-list" style="padding-left: 10px;padding-right: 10px;" cdkDropList [cdkDropListData]="data"
           (cdkDropListDropped)="drop($event)">
    <ng-container *ngFor="let product of data; let  j = index;">
      <li class="mdc-image-list__item" cdkDrag>
        <div class="mdc-image-list__image-aspect-container">
          <ng-container *ngIf="product.image == null; else productImage">
            <img src="" class="mdc-image-list__image imagenotfound">
          </ng-container>
          <ng-template #productImage>
            <img [src]="product.image" class="mdc-image-list__image">
          </ng-template>
        </div>
        <div class="mdc-image-list--with-text-protection">
        <div class="mdc-image-list__supporting mdc-image-list__supporting">
        <span class="mdc-image-list__label">{{product.name}}</span>
        </div>
        </div>
      </li>
    </ng-container>
  </ul>

.ts

    drop(event: CdkDragDrop<string[]>) {
    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
      );
    }
  }

Изображения


person mvp Sets    schedule 16.03.2020    source источник


Ответы (1)


Единственный способ разрешить перетаскивание в сетке, который я нашел, - это то, что каждый элемент сетки был одним cdkDropList.

Реклама: элементы не двигаются, пока мы перетаскиваем

Что ж, поскольку данные каждого cdkDropList будут объектом, данные, которые мы хотим транспортировать, и индекс

[cdkDropListData]="{item:product,index:j}"

Итак, наша функция dropEvent меняет данные массива в соответствии с этими значениями.

  drop(event: CdkDragDrop<any>) {
    this.data[event.previousContainer.data.index]={...event.container.data.item}
    this.data[event.container.data.index]={...event.previousContainer.data.item}
    event.currentIndex=0;
  }

Да! мы не обязаны использовать каплю, как показывают примеры. Подумайте, что единственное, что нам нужно, - это изменить массив.

Есть еще одна вещь, которую нужно сделать: сделать так, чтобы dragPlaceHolder стал пустым div.

<div cdkDrag>
     ....
    <div  *cdkDragPlaceholder></div>
</div>

Ну, html несколько сложен, потому что собственный mdc-image-list сложен. Важно отметить, что весь cdkDropList должен быть заключен в div ckdDropListGroup.

<div cdkDropListGroup>

    <ul class="mdc-image-list my-image-list" style="padding-left: 10px;padding-right: 10px;">
        <ng-container *ngFor="let product of data; let  j = index;">
            <li class="mdc-image-list__item" cdkDropList [cdkDropListData]="{item:product,index:j}"
                cdkDropListOrientation="horizontal" (cdkDropListDropped)="drop($event)">
                <div cdkDrag>
                    <div class="mdc-image-list__image-aspect-container">
                        <ng-container *ngIf="product.image == null; else productImage">
                            <img src="" class="mdc-image-list__image imagenotfound">
          </ng-container>
                            <ng-template #productImage>
                                <img [src]="product.image" class="mdc-image-list__image">
          </ng-template>
                    </div>
                    <div class="mdc-image-list--with-text-protection">
                        <div class="mdc-image-list__supporting mdc-image-list__supporting">
                            <span class="mdc-image-list__label">{{product.name}}</span>
                        </div>
                    </div>
                    <div class="example-custom-placeholder" *cdkDragPlaceholder></div>
                </div>
            </li>
        </ng-container>
    </ul>
</div>

вот ваш раздвоенный stackblitz

ПРИМЕЧАНИЕ. Если кому-то нужен более простой пример, см. Этот другой stackblitz

person Eliseo    schedule 16.03.2020
comment
Привет, я нашел еще один замечательный пример в stackblitz.com/ edit /, из c3rber, не забудьте проверить это (обсуждение в github - github.com/angular/components/issues/13372 - person Eliseo; 17.03.2020
comment
Есть ли способ перетащить изображение, используя cdk перетаскивания или нет, в зону перетаскивания, и при перетаскивании этого изображения я могу извлечь данные из этого брошенного изображения? - person mvp Sets; 17.03.2020
comment
Если вы можете мне помочь, я обновил ссылку. При необходимости я могу создать новый вопрос. - person mvp Sets; 17.03.2020
comment
используя @ angular / cdk / drag-drop, у вас есть два cdkList, один - список изображений с [cdkDropListConnectedTo]="[dropZone]" другим, ваш div, в который вы хотите поместить изображения: <div class="card selectionCard" cdkDropList #dropZone="cdkDropList" (cdkDropListDropped)="dropOnZone($event)" [cdkDropListData]="null"> посмотрите, что необходимо также добавить ckdDrag в зону перетаскивания. В функции dropOnZone у вас есть данные элемента, который вы перетаскиваете event.previousContainer.data[event.previousIndex], см. stackblitz.com/edit/ - person Eliseo; 18.03.2020