I have multiple CdkDrag element that are rendered from a ngFor loop on an array in my component. when i remove one element i splice the array. Then some of the elements will update there position. how do i avoid that?
I tried to get the freeDragPosition of all the draggable element before deleting one of them, then to reset their position, but it did not work.
this is my 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>
and this is my 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}
}
I would like for my element to remain in their current position when one of the element was deleted.
here's a .gif representing the problem
here's a stackblitz https://stackblitz.com/edit/angular-p3yfe7
positions.forEach(p => { ... })
inside youronRemoveTextField
. What's the use of that? If I comment it out it works well – Collop