I have a list of items and I need to drag and drop each of the item to a droppable container. I am using copyArrayItem
from @angular/cdk/drag-drop
. Also, I want to update some properties of each item after droping it to the droppable container.
The problem I'm facing is, if I drag and drop 'Item-1' two times to the droppable container and if I update the properties of one among it, then it results in the update of both item's properties.
How can I fix this, or how can I update a unique item after dropping it to the droppable container?
component.html
<div>
<div class="jfs-container">
<div class="jfs-actions">
<button mat-raised-button class="btn-clear" (click)="clearForm()">
<mat-icon>clear</mat-icon>
</button>
<button mat-raised-button class="btn-generate" (click)="generateForm()">Save</button>
</div>
<div class="jfs-wrapper">
<div class="jfs-builder">
<div class="jfs-controls" cdkDropList #controlList="cdkDropList" [cdkDropListData]="controls"
cdkDropListSortingDisabled [cdkDropListConnectedTo]="[previewList]"
(cdkDropListDropped)="dropControl($event)" (cdkDropListExited)="dropListExited($event)"
(cdkDropListEntered)="dropListEntered()">
<div class="jfs-display" *ngFor="let control of controls" cdkDrag [cdkDragData]="control">
<div class="jfs-display" *cdkDragPlaceholder>
<a> {{ control.displayName }} </a>
</div>
<a> {{ control.displayName }} </a>
</div>
</div>
</div>
<div class="jfs-previewer">
<div class="jfs-dropper" cdkDropList #previewList="cdkDropList" [cdkDropListData]="generatedControls"
(cdkDropListDropped)="dropControl($event)">
<span *ngIf="generatedControls.length === 0" class="jfs-drag-info">Drag and drop an item</span>
<div class="jfs-component" *ngFor="let control of generatedControls; let controlIndex=index;"
cdkDrag>
<ng-container [ngSwitch]="control.type">
<div class="jfs-btn-group">
<mat-icon (click)="deleteComponent(control, controlIndex)" class="delete">delete_forever
</mat-icon>
<mat-icon (click)="openDetailsEditorDialog(control, controlIndex)" class="edit">edit
</mat-icon>
</div>
<div *ngSwitchCase="'itemOne'">
Item One
</div>
<div *ngSwitchCase="'itemTwo'">
Item Two
</div>
</ng-container>
</div>
</div>
</div>
</div>
</div>
<code>{{ UIDisplay }}</code>
</div>
component.ts
import { copyArrayItem, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { ControlType } from '../interface/control-type';
import { ControlEditorModalComponent } from '../modal/control-editor-modal/control-editor-modal.component';
import { Controls } from '../utils/controls/controls';
@Component({
selector: 'app-form-structurizer',
templateUrl: './form-structurizer.component.html',
styleUrls: ['./form-structurizer.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class FormStructurizerComponent implements OnInit {
public controls: Array<ControlType> = Controls;
public generatedControls: Array<ControlType> = [];
public UIDisplay: any;
constructor(
private dialog: MatDialog
) { }
ngOnInit(): void {
}
dropControl(event: any): void {
if (event.previousContainer !== event.container) {
copyArrayItem(event.previousContainer.data, event.container.data, event.previousIndex, event.currentIndex);
this.openDetailsEditorDialog(event);
} else {
moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
}
if (event.previousContainer.data) {
this.controls = this.controls.filter((control) => !control.droppedFlag);
}
}
dropListExited(event: any): void {
const currentIndex = event.container.data.findIndex(
(control: ControlType) => control.type === event.item.data.type
);
this.controls.splice(currentIndex + 1, 0, {
...event.item.data,
droppedFlag: true,
});
}
dropListEntered(): void {
this.controls = this.controls.filter((control) => !control.droppedFlag);
}
openDetailsEditorDialog(event: any, index?: number): void {
let control: ControlType = { displayName: '', type: '' };
if (event?.container) {
control = event?.container?.data[event?.currentIndex];
index = event?.currentIndex;
} else if (event?.displayName) {
control = event;
}
this.dialog.open(ControlEditorModalComponent, {
width: '900px',
disableClose: true,
panelClass: 'control-editor-modal',
data: {
control: control
},
}).afterClosed().subscribe((result: any) => {
if (result && index !== undefined)
this.update(result, index);
});
}
update(jsonComponent: any, index: number): void {
if (jsonComponent && index !== undefined) {
this.generatedControls[index].struct = JSON.parse(jsonComponent);
}
}
deleteComponent(control: ControlType, index: number): void {
this.generatedControls.splice(index, 1);
}
clearForm(): void {
this.generatedControls = [];
}
generateForm(): void {
let formGenerated: any = { "components": [] }
this.generatedControls.forEach((control: ControlType) => {
if (control.struct) {
formGenerated.components.push(control.struct);
}
});
this.UIDisplay = formGenerated;
}
}
Please find the image of the sample project.