Drawflow Tutorial: 3. Add Nodes Through Drag and Drop
In the last tutorial, we covered how to programmatically add and connect nodes using editor.import(). Now, let’s make things more interactive by enabling users to drag and drop nodes into the canvas. This feature is perfect for creating a dynamic interface where users can customize workflows.
Here’s how you can implement drag-and-drop functionality to add nodes.
Step 1: Set Up a Basic HTML Structure
To start, we need:
- A container for the Drawflow canvas.
- A list of options that users can drag into the canvas.
Here’s a simple HTML structure:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Drawflow Drag and Drop</title>
<link rel="stylesheet" href="https://unpkg.com/drawflow@0.0.60/dist/drawflow.min.css">
<script src="https://unpkg.com/drawflow@0.0.60/dist/drawflow.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
.page-container {
display: flex;
height: 100vh;
}
.drag-items {
display: flex;
flex-direction: column;
gap: 10px;
width: 300px;
padding: 20px;
border-right: 2px solid #ddd;
}
.drag-item {
background-color: rgb(159 18 57);
color: #fee;
padding: 10px 20px;
border-radius: 4px;
font-size: 1.2rem;
}
.drawflow-column {
flex: 1;
border: 2px solid #ddd;
margin: 40px;
border-radius: 10px;
}
.drawflow {
height: 100%;
}
</style>
</head>
<body>
<div class="page-container">
<!-- Sidebar with draggable options -->
<div class="drag-items">
<div class="drag-item" draggable="true" data-node="node1">Node 1</div>
<div class="drag-item" draggable="true" data-node="node2">Node 2</div>
</div>
<div class="drawflow-column">
<!-- Drawflow Canvas -->
<div id="drawflow" class="drawflow"></div>
</div>
</div>
<script>
const drawflowContainer = document.getElementById('drawflow');
const editor = new Drawflow(drawflowContainer);
editor.start();
</script>
</body>
</html>
Explanation
- Sidebar (
.drag-items): Contains two draggable items, each with adata-nodeattribute to identify the node type. - Canvas (
#drawflow): The main canvas where nodes will be dropped.

Step 2: Enable Drag-and-Drop Functionality
Drawflow has built-in support for drag-and-drop. To enable it, we need to:
- Attach
draggableattributes to the sidebar items. - Set up event listeners for drag-and-drop actions.
Here’s how to wire up the logic:
// Enable drag from the sidebar
const dragItems = document.querySelectorAll('.drag-item');
dragItems.forEach(item => {
item.addEventListener('dragstart', event => {
event.dataTransfer.setData('node', event.target.getAttribute('data-node'));
});
});
// Enable drop on the canvas
drawflowContainer.addEventListener('drop', event => {
event.preventDefault();
const nodeName = event.dataTransfer.getData('node');
const { x, y } = editor.precanvas.getBoundingClientRect();
const posX = event.clientX - x;
const posY = event.clientY - y;
addNewNode(nodeName, posX, posY);
});
// Select the node equivalent to the item that has been dropped over the canvas
function addNewNode(name, pos_x, pos_y) {
switch (name) {
case 'node1':
const node1 = `<div>Node 1 Content with output</div>`
editor.addNode('Node 1', 0, 1, pos_x, pos_y, '', {}, node1 );
break;
case 'node2':
const node2 = `<div>Node 2 Content with input</div>`
editor.addNode('Node 2', 1, 0, pos_x, pos_y, '', {}, node2 );
break;
case 'node3':
const node3 = `<div>Node 3 Content with input and output</div>`
editor.addNode('Node 3', 1, 1, pos_x, pos_y, '', {}, node3 );
break;
}
}
// Prevent default behavior for dragover
drawflowContainer.addEventListener('dragover', event => {
event.preventDefault();
});
Step 3: Test the Drag-and-Drop
Here’s the complete setup:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Drawflow Drag and Drop</title>
<link rel="stylesheet" href="https://unpkg.com/drawflow@0.0.60/dist/drawflow.min.css">
<script src="https://unpkg.com/drawflow@0.0.60/dist/drawflow.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
.page-container {
display: flex;
height: 100vh;
}
.drag-items {
display: flex;
flex-direction: column;
gap: 10px;
width: 300px;
padding: 20px;
border-right: 2px solid #ddd;
}
.drag-item {
background-color: rgb(159 18 57);
color: #fee;
padding: 10px 20px;
border-radius: 4px;
font-size: 1.2rem;
}
.drawflow-column {
flex: 1;
border: 2px solid #ddd;
margin: 40px;
border-radius: 10px;
}
.drawflow {
height: 100%;
}
</style>
</head>
<body>
<div class="page-container">
<!-- Sidebar with draggable options -->
<div class="drag-items">
<div class="drag-item" draggable="true" data-node="node1">Node 1</div>
<div class="drag-item" draggable="true" data-node="node2">Node 2</div>
<div class="drag-item" draggable="true" data-node="node3">Node 3</div>
</div>
<div class="drawflow-column">
<!-- Drawflow Canvas -->
<div id="drawflow" class="drawflow"></div>
</div>
</div>
<script>
const drawflowContainer = document.getElementById('drawflow');
const editor = new Drawflow(drawflowContainer);
editor.start();
// Enable drag from the sidebar
const dragItems = document.querySelectorAll('.drag-item');
dragItems.forEach(item => {
item.addEventListener('dragstart', event => {
event.dataTransfer.setData('node', event.target.getAttribute('data-node'));
});
});
// Enable drop on the canvas
drawflowContainer.addEventListener('drop', event => {
event.preventDefault();
const nodeName = event.dataTransfer.getData('node');
const { x, y } = editor.precanvas.getBoundingClientRect();
const posX = event.clientX - x;
const posY = event.clientY - y;
addNewNode(nodeName, posX, posY);
});
function addNewNode(name, pos_x, pos_y) {
switch (name) {
case 'node1':
const node1 = `<div>Node 1 Content with output</div>`
editor.addNode('Node 1', 0, 1, pos_x, pos_y, '', {}, node1 );
break;
case 'node2':
const node2 = `<div>Node 2 Content with input</div>`
editor.addNode('Node 2', 1, 0, pos_x, pos_y, '', {}, node2 );
break;
case 'node3':
const node3 = `<div>Node 3 Content with input and output</div>`
editor.addNode('Node 3', 1, 1, pos_x, pos_y, '', {}, node3 );
break;
}
}
// Prevent default behavior for dragover
drawflowContainer.addEventListener('dragover', event => {
event.preventDefault();
});
</script>
</body>
</html>
You should get the following end result:
