DHTMLX Kanban. Custom context menu example
The default card menu offers basic actions (duplicate, delete), but workflows often need context-specific options: setting progress, changing assignees, or applying labels. Custom menus let you define different menu items per card and per column, with direct access to card/column data in the handlers.
Live example
const { Kanban, getDefaultCardMenuItems } = kanban;
const board = new Kanban("#root", {
columns,
cards,
rows,
rowKey: "type",
cardShape: {
...cardShape,
menu: {
show: true,
items: ({ card, readonly }) => {
const defaultMenuItems = getDefaultCardMenuItems({
card,
readonly,
});
if (card.column === "backlog") {
return defaultMenuItems;
}
return [
{
id: "set-edit",
text: "Edit",
icon: "wxi-edit",
},
{
id: "progress",
text: "Set progress",
icon: "wxi-edit",
onClick: ({ card }) => {
board.updateCard({
id: card.id,
card: { ...card, progress: 100 },
});
},
},
];
},
},
},
columnShape: {
menu: {
items: ({ column }) => {
const items = [
{
id: "delete-card",
icon: "wxi-delete",
text: "Remove card",
onClick: ({ column }) => {
board.deleteCard({
id: board.getAreaCards(column.id)[0].id,
});
},
},
];
if (column.id === "backlog") {
items.push({
id: "add-card",
icon: "fas fa-plus",
text: "Add card",
});
}
return items;
},
},
},
});
new kanban.Toolbar("#toolbar", {
api: board.api,
items: ["search", "spacer", "sort", "addColumn", "addRow"],
});
<!-- font awesome icons -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" integrity="sha512-KfkfwYDsLkIlwQp6LFnl8zNdLGxu9YAA1QvwINks4PhcElQSvqcyVLLD9aMhXd13uQjoXtEKNosOWaZqXgel0g==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<!-- component containers -->
<div id="toolbar"></div>
<div id="root" style="height: calc(100% - 56px);"></div>
<!-- dataset -->
<script>
const users = [
{
id: 1,
label: "Steve Smith",
avatar: "https://snippet.dhtmlx.com/codebase/data/kanban/01/img/user-1.jpg",
},
{
id: 2,
label: "Aaron Long",
avatar: "https://snippet.dhtmlx.com/codebase/data/kanban/01/img/user-2.jpg",
},
{
id: 3,
label: "Angela Allen",
avatar: "https://snippet.dhtmlx.com/codebase/data/kanban/01/img/user-3.jpg",
},
{
id: 4,
label: "Angela Long",
avatar: "https://snippet.dhtmlx.com/codebase/data/kanban/01/img/user-4.jpg",
},
{
id: 5,
label: "John Doe",
},
];
const cardShape = {
label: true,
description: true,
progress: true,
start_date: true,
end_date: true,
users: {
show: true,
values: users,
},
priority: {
show: true,
values: [
{ id: 1, color: "#FF5252", label: "High" },
{ id: 2, color: "#FFC975", label: "Medium" },
{ id: 3, color: "#65D3B3", label: "Low" },
],
},
color: true,
menu: true,
cover: true,
attached: false,
};
const columns = [
{
label: "Backlog",
id: "backlog",
},
{
label: "In progress",
id: "inprogress",
},
{
label: "Testing",
id: "testing",
},
{
label: "Done",
id: "done",
},
];
const rows = [
{
label: "Feature",
id: "feature",
},
{
label: "Task",
id: "task",
},
];
const cards = [
{
label: "Integration with Angular/React",
priority: 1,
color: "#65D3B3",
start_date: new Date("01/07/2021"),
users: [3, 2],
column: "backlog",
type: "feature",
},
{
label: "Archive the cards/boards ",
priority: 3,
color: "#58C3FE",
users: [5],
progress: 1,
column: "backlog",
type: "feature",
},
{
label: "Searching and filtering",
priority: 1,
color: "#58C3FE",
start_date: new Date("01/09/2021"),
users: [3, 1],
progress: 1,
column: "backlog",
type: "task",
},
{
label: "Set the tasks priorities",
color: "#FFC975",
start_date: new Date("12/21/2020"),
users: [4],
progress: 75,
column: "inprogress",
type: "feature",
attached: [
{
isCover: true,
coverURL:
"https://snippet.dhtmlx.com/codebase/data/kanban/01/img/img-1.jpg",
previewURL:
"https://snippet.dhtmlx.com/codebase/data/kanban/01/img/img-1.jpg",
url: "https://snippet.dhtmlx.com/codebase/data/kanban/01/img/img-1.jpg",
name: "img-1.jpg",
},
],
},
{
label: "Custom icons",
color: "#65D3B3",
start_date: new Date("01/07/2021"),
users: [3, 2],
column: "inprogress",
type: "task",
},
{
label: "Integration with Gantt",
color: "#FFC975",
start_date: new Date("12/21/2020"),
users: [4],
progress: 75,
column: "inprogress",
type: "task",
},
{
label: "Drag and drop",
priority: 1,
color: "#58C3FE",
users: [3, 1],
progress: 100,
column: "testing",
type: "feature",
},
{
label: "Adding images",
color: "#58C3FE",
users: [4],
column: "testing",
type: "task",
attached: [
{
isCover: true,
coverURL:
"https://snippet.dhtmlx.com/codebase/data/kanban/01/img/img-2.jpg",
previewURL:
"https://snippet.dhtmlx.com/codebase/data/kanban/01/img/img-2.jpg",
url: "https://snippet.dhtmlx.com/codebase/data/kanban/01/img/img-2.jpg",
name: "img-2.jpg",
},
],
},
{
label: "Create cards and lists from the UI and from code",
priority: 3,
color: "#65D3B3",
start_date: new Date("01/07/2021"),
users: [3, 2],
column: "done",
type: "feature",
},
{
label: "Draw swimlanes",
color: "#FFC975",
users: [2],
column: "done",
type: "feature",
},
{
label: "Progress bar",
priority: 1,
color: "#FFC975",
start_date: new Date("12/9/2020"),
users: [1, 4, 3],
progress: 100,
column: "done",
type: "task",
},
];
</script>The code customizes both card and column menus. The card menu.items is a function that checks card.column. Backlog cards get the default menu (via getDefaultCardMenuItems), while other cards get a custom menu with "Edit" and "Set progress" actions. The column menu uses a function that always includes a "Remove card" item and conditionally adds "Add card" only for the Backlog column. Menu items support icon, text, id, and onClick properties.
Solution overview
- Set
cardShape.menu.itemsto a function receiving{ card, readonly }and returning menu items - Use
getDefaultCardMenuItems({ card, readonly })to include default items when needed - Add custom items with
onClickhandlers that call Kanban methods - Set
columnShape.menu.itemsto a function receiving{ column }for column-specific menus - Use built-in action IDs like
"set-edit"and"add-card"to trigger standard Kanban actions
Key points
getDefaultCardMenuItemsas a starting point: Import it from the Kanban package to extend rather than replace the default menu- Function-based items: Using a function instead of a static array lets you return different menus per card/column based on their data
- Built-in action IDs: Menu items with
id: "set-edit"orid: "add-card"trigger the corresponding Kanban action automatically. NoonClickneeded - Custom actions need
onClick: For custom items like "Set progress", define anonClickthat callsboard.updateCardor other API methods - Font Awesome icons: The demo loads Font Awesome for
"fas fa-plus"icon class. Use any icon library or the built-in"wxi-"icon classes
API reference
- cardShape.menu: Card menu configuration
- columnShape.menu: Column menu configuration
- getDefaultCardMenuItems: Returns the default card menu items