web-dev-qa-db-fra.com

Position de mise à jour de CdkDrag

J'ai plusieurs éléments CdkDrag qui sont rendus à partir d'une boucle ngFor sur un tableau de mon composant. lorsque je supprime un élément, je raccorde le tableau. Ensuite, certains des éléments mettront à jour leur position. comment éviter cela?

J'ai essayé d'obtenir la freeDragPosition de tous les éléments glissables avant de supprimer l'un d'eux, puis de réinitialiser leur position, mais cela n'a pas fonctionné.

c'est mon app.component.html

<div class="container" id="container">
  <div *ngFor="let f of fields; let i = index;" 
    class="textField"
    [attr.data-guid]="f.guid"  
    (mouseenter)="onFieldHover($event)" 
    cdkDrag 
    cdkDragBoundary="#container"
    (cdkDragEnded)="onDragEnded($event)"
    [cdkDragFreeDragPosition]="f.position">
    <div class="textField-inner">
      <span style="color: hotpink; font-weight: bold">{{f.guid}}</span>
    </div>
    <div class="textField-options">
      <div class="textField-move" cdkDragHandle>
        <svg width="24px" fill="currentColor" viewBox="0 0 24 24">
          <path d="M10 9h4V6h3l-5-5-5 5h3v3zm-1 1H6V7l-5 5 5 5v-3h3v-4zm14 2l-5-5v3h-3v4h3v3l5-5zm-9 3h-4v3H7l5 5 5-5h-3v-3z"></path>
          <path d="M0 0h24v24H0z" fill="none"></path>
        </svg>
      </div>
      <div class="textField-remove">
        <i class="fas fa-trash-alt" (click)="onRemoveTextField(i)"></i>
      </div>
    </div>
  </div>
</div>
<button type="button" (click)="onTextFieldAdded()">Add a field</button>

et voici mon app.component.ts

import { Component } from '@angular/core';
import {CdkDrag, CdkDragEnd} from '@angular/cdk/drag-drop';


@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.scss' ]
})
export class AppComponent  {
  name = 'Angular';
  fields: Field[] = [];
    draggables: CdkDrag<any>[] = [];


  onDragEnded(event: CdkDragEnd){
        if(!this.draggables.find(f => f == event.source)){
            this.draggables.Push(event.source);
        }
    }

  onFieldHover(event: any){
        if(event.target.classList.contains('initialPosition')){
            event.target.classList.remove('initialPosition');
            event.target.style.transform = "translate3d(250px, 180px, 0px)";
        }
    }

  onTextFieldAdded() {
        let field = new Field();
        field.index = this.fields.length;
        field.guid = this.newGuid();

        this.fields.Push(field);
    }

  onRemoveTextField(index: number){
    let positions : any[] =[];

        this.draggables.forEach(drag => {
            let pos = { guid: drag.element.nativeElement.getAttribute("data-guid"), pos: drag.getFreeDragPosition()  };
            positions.Push(pos);
            console.log(pos);
        });

        this.fields.splice(index, 1);

    positions.forEach(p => {
      let newPos = {x: p.pos.x, y: p.pos.y};
      console.log(newPos);
      this.fields.find(f => f.guid == p.guid).position = newPos;
        });
    }

  newGuid(): string{
     return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
            var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
            return v.toString(16);
        });
  }

}

export class Field{
    index: number;
    guid: string;
    position: {x: number, y: number}
}


Je souhaite que mon élément reste dans sa position actuelle lorsque l'un des éléments a été supprimé.

voici un .gif représentant le problème element moving has i delete one

voici un stackblitz https://stackblitz.com/edit/angular-p3yfe7

4
Francis Groleau

Le problème est que vous n'avez pas spécifié de fonction trackBy dans votre *ngFor, cela provoquera un nouveau rendu des objets chaque fois que le tableau change:

Vous devez créer votre *ngFor comme ça:

*ngFor="let f of fields; let i = index; trackBy: trackByField"

Et mettez à jour votre composant pour avoir une méthode trackByField

 trackByField = (i: number, field: Field) => field.guid;

Ensuite, les éléments qui ont déjà été déplacés restent dans leur position et les éléments non déplacés seront toujours réorganisés

pile

0
PierreDuc