Implementing Node Swapping with Drag and Drop in an Organizational Chart
Organizational charts (org charts) are an essential tool for visualizing hierarchical structures. One common requirement when managing org charts is the ability to swap nodes while maintaining structural integrity. In this article, we will walk through how to implement node swapping in an org chart using JavaScript and the OrgChart JS library.
Understanding the Requirements
Swapping nodes in an org chart involves moving one node to the position of another while ensuring that the hierarchical relationships remain intact. Specifically, we need to handle the following scenarios:
Swapping nodes at the same level – Nodes exchange positions without affecting their parent-child relationships.
Swapping parent-child nodes – The parent becomes the child and vice versa.
Swapping nodes at different levels – A more complex case where structural adjustments are necessary.
Code example
Setting Up the Org Chart
We will initialize our org chart using the OrgChart JS library and enable drag-and-drop functionality.
let chart = new OrgChart(document.getElementById("tree"), {
mode: 'dark',
enableDragDrop: true,
mouseScrool: OrgChart.none,
nodeBinding: {
field_0: "id",
field_1: "pid",
},
orderBy: 'order'
});
Loading Sample Data
Finally, we initialize the org chart with sample data to visualize the swapping functionality.
chart.load([
{ id: 1, order: 1 },
{ id: 2, pid: 1, order: 2 },
{ id: 3, pid: 1, order: 3 },
{ id: 4, pid: 2, order: 4 },
{ id: 5, pid: 2, order: 5 },
{ id: 6, pid: 3, order: 6 },
{ id: 7, pid: 3, order: 7 }
]);
Handling the Drag-and-Drop Event
To implement node swapping, we listen to the onDrop
event, retrieve the drag-and-drop node data, and handle different scenarios appropriately.
Swapping Nodes at the Same Level
If the dragged node and the target node are at the same level, we swap their order
values and update the chart:
if (dragNode.level == dropNode.level){
let temp = dropData.order;
dropData.order = dragData.order;
dragData.order = temp;
temp = dropData.pid;
dropData.pid = dragData.pid;
dragData.pid = temp;
chart.update(dropData).update(dragData).draw();
}
Swapping Parent-Child Nodes
If a node is being swapped with its parent, we must update all child nodes accordingly:
else if (dragData.pid == dropData.id || dragData.id == dropData.pid){
for(let i = 0; i < chart.config.nodes.length; i++ ){
let data = chart.config.nodes[i];
if (data.pid == args.dropId){
data.pid = args.dragId;
}
else if (data.pid == args.dragId){
data.pid = args.dropId;
}
}
if (dragData.pid == dropData.id){
let temp = dragData.pid;
dragData.pid = dropData.pid;
dropData.pid = dragData.id;
}
else if (dragData.id == dropData.pid){
let temp = dropData.pid;
dropData.pid = dragData.pid;
dragData.pid = dropData.id;
}
let temp = dropData.order;
dropData.order = dragData.order;
dragData.order = temp;
chart.update(dropData).update(dragData).draw();
}
Swapping Nodes at Different Levels
When swapping nodes that belong to different hierarchical levels, we must adjust their pid
values and reorder them:
else {
for(let i = 0; i < chart.config.nodes.length; i++ ){
let data = chart.config.nodes[i];
if (dragNode.level > dropNode.level && data.pid == args.dropId){
data.pid = args.dragId;
}
else if (dragNode.level < dropNode.level && data.pid == args.dragId){
data.pid = args.dropId;
}
chart.update(data);
}
temp = dragData.pid;
dragData.pid = dropData.pid;
dropData.pid = temp;
temp = dropData.order;
dropData.order = dragData.order;
dragData.order = temp;
chart.update(dropData).update(dragData).draw();
}
Swapping nodes in an org chart requires careful handling of parent-child relationships and order values. By leveraging the onDrop
event and modifying the pid
and order
attributes accordingly, we can implement a flexible swapping mechanism that ensures the chart remains structured and functional.
Swap nodes
This implementation allows for seamless reorganization of an org chart, making it a valuable feature for applications that require dynamic hierarchical adjustments.