I’m trying to implement drag and drop functionality between two JSONs to map the keys of one JSON to another. I created the JsonViewerComponent that accepts JSON data as input and displays it using recursion. Primary key is also passed in the component that gives the flattened keys at every leaf node in the recursive tree. The JsonViewerComponent also accepts a flag isSourceJson which is used to display either a draggable element (having the flattened keys) after every key value pair in the JSON structure, or an element that acts as drop zone where the draggable element will be dropped.
The problem that I’m facing is that in my draggable element, (dragstart) event is not working properly. The event gets fired but the drag effect is not visible in the UI. But when I change the (dragstart) event to (drag) event or event remove it, then the drag effect is visible in the UI. Similarly, in the drop zone element at the target JSON, (drop) event is not working even though (dragover) event is firing, but (drop) event is not fired.
Below is my code and also the stackblitz.
app.componnet.html
<div class="parent-container h-100">
<div id="sourceJson" class="json-container border">
<app-json-viewer [data]="sourceJson" [isSourceJson]="true"></app-json-viewer>
</div>
<div id="destinationJson" class="json-container border">
<app-json-viewer [data]="destinationJson" [isSourceJson]="false"></app-json-viewer>
</div>
</div>
json-viewer.component.html
<ng-container *ngIf="data">
<ng-container *ngIf="isObject(data)">
<span>{{'{'}}</span><br>
<div *ngFor="let item of getFormattedData(data)" [style.marginLeft.px]="20">
<span>{{item.key}}: </span><app-json-viewer [data]="item.value" [previousKey]="previousKey+item.key+'.'" [isSourceJson]="isSourceJson"></app-json-viewer>
</div>
<span>{{'}'}}</span>
</ng-container>
<ng-container *ngIf="isArray(data)">
<span>{{'['}}</span><br>
<div *ngFor="let item of data" [style.marginLeft.px]="20">
<app-json-viewer [data]="item" [previousKey]="previousKey" [isSourceJson]="isSourceJson"></app-json-viewer>
</div>
<span>{{']'}}</span><br>
</ng-container>
<ng-container *ngIf="!isObject(data) && !isArray(data)">
<span>{{data}},</span>
<ng-container *ngIf="isSourceJson">
<span class="draggable" draggable="true" (drag)="onDrag()">{{previousKey.slice(0, -1)}}</span>
</ng-container>
<ng-container *ngIf="!isSourceJson">
<span class="drop-area" (dragover)="onDragOver($event)" (drop)="onDrop($event)">{{ sourceKey }}</span>
</ng-container>
</ng-container>
</ng-container>
json-viewer.component.ts
import { Component, Input, OnChanges, OnInit } from '@angular/core';
@Component({
selector: 'app-json-viewer',
templateUrl: './json-viewer.component.html',
styleUrls: ['./json-viewer.component.less']
})
export class JsonViewerComponent {
@Input() data: any;
@Input() previousKey: string = '';
@Input() isSourceJson: boolean = true;
sourceKey?: string;
onButtonClick(key: string, value: any) {
console.log(`Button clicked for key: ${key}, value: ${value}`);
}
isObject(val: any): boolean {
return val && typeof val === 'object' && !Array.isArray(val);
}
isArray(val: any): boolean {
return Array.isArray(val);
}
getFormattedData(data: any): Array<{ key: string, value: any }> {
let result = [];
for (let key in data) {
if (data.hasOwnProperty(key)) {
result.push({ key, value: data[key] });
}
}
return result;
}
// TODO
onDrag() {
console.log('dragging')
}
onDragStart(event: any, key: string) {
console.log("start");
event?.dataTransfer?.setData('text/plain', key);
event.dataTransfer.effectAllowed = "move";
}
onDragOver(event: any) {
event.dataTransfer.effectAllowed = "move";
event.preventDefault();
}
onDrop(event: any) {
console.log('dropped')
event.dataTransfer.effectAllowed = "move";
const data = event?.dataTransfer?.getData('text/plain');
// const div = document.getElementById(data);
// const clone = div?.cloneNode(true);
// event.target.appendChild(clone);
if(data) this.sourceKey = data;
event?.dataTransfer?.clearData?.();
}
}
stackblitz:
sooraj is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.