DHTMLX Kanban. Disabling drag and drop to specific columns example
Some columns should only be populated by specific roles or through automated processes. For instance, only testers should move cards to "Done", or only a CI pipeline should mark tasks as deployed. Disabling drag-and-drop to specific columns enforces these workflow rules directly in the UI.
Live example
const { Kanban, template } = kanban;
const { columns, cards } = getData();
const board = new Kanban("#root", {
columns,
cards,
});
let startCol;
board.api.on("start-drag-card", ({ columnId }) => {
startCol = columnId;
if (startCol != "done")
board.api.exec("update-column", {
id: "done",
column: {
overlay: template(`
<div class="blockOverlay disable-drop">
<span class="disable-drop-header">Drop is not allowed</span>
<span class="disable-drop-description">Only testers can move cards to this
column</span>
</div>`),
},
});
});
board.api.intercept("drag-card", ({ columnId }) => {
if (startCol != "done" && columnId == "done") return false;
});
board.api.intercept("move-card", ({ columnId }) => {
if (startCol != "done")
board.api.exec("update-column", {
id: "done",
column: {
overlay: null,
},
});
if (columnId == "done") return false;
}); <!-- custom styles -->
<style>
.disable-drop {
text-align: center;
position: absolute;
top: 0;
height: 100%;
width: 100%;
display: flex;
justify-content: center;
flex-direction: column;
background: rgba(247, 247, 247, 0.8);
border: 1px dashed #ededed;
border-radius: 6px;
}
.disable-drop-header {
font-weight: 500;
}
.disable-drop-description {
color: var(--wx-color-font-alt);
padding: 0 28px;
}
.wx-collapsed .disable-drop-description {
display: none;
}
.wx-collapsed .disable-drop-header {
display: flex;
align-items: center;
writing-mode: tb-rl;
transform: rotate(180deg);
}
</style>The code uses three event handlers working together. on("start-drag-card") records the source column and applies a visual overlay on the "Done" column using update-column with a template() overlay. intercept("drag-card") returns false when the target is "Done" and the source isn't, preventing the card from entering the column during drag. intercept("move-card") blocks the final move and removes the overlay. The overlay uses template() to render a "Drop is not allowed" message with custom styling.
Solution overview
- Listen to
start-drag-cardto track the source column and show a blocking overlay on restricted columns - Intercept
drag-cardto returnfalsewhen dragging to a restricted column. This prevents the visual drag feedback - Intercept
move-cardto block the actual move and clean up the overlay (setoverlay: null) - Style the overlay with CSS for a clear visual indication
Key points
- Three-event pattern: Blocking drops properly requires handling
start-drag-card,drag-card, andmove-card. Skipping any of these leaves gaps in the UX - Column overlays are dynamic:
update-columnwith anoverlayproperty renders content over the column. Set tonullto remove template()for overlays: The overlay content must be wrapped intemplate()for proper rendering
API reference
- api.on: Subscribes to events
- api.intercept: Intercepts and blocks events
- template: Creates reactive templates for overlays and custom rendering