DHTMLX Kanban. Template for column headers example
The default column header shows a collapse icon, the label, and a menu icon, but many teams need additional information: card counts, limit indicators, or custom actions. Column header templates let you fully control the header HTML while still integrating with the Kanban's built-in interactions like collapse, rename, and context menu.
Live example
const { Kanban, template } = kanban;
// escape html characters in a string
function escapeHTML(str) {
return str.replace(
/[&<>'"]/g,
tag =>
({
"&": "&",
"<": "<",
">": ">",
"'": "'",
'"': """,
}[tag] || tag)
);
}
function columnHeaderTemplate({
readonly,
isMenuVisible,
column,
columnState,
renaming,
}) {
return `<div class="wx-collapse-icon" data-action=${"collapse"}>
<i class=${column.collapsed ? "wxi-angle-right" : "wxi-angle-left"}></i>
</div>
${
!renaming && !column.collapsed
? `<div class="wx-label" data-action="rename">
${escapeHTML(column.label)}
(${columnState.cardsCount})
${column.limit ? `(${columnState.cardsCount}/${columnState.totalLimit})` : ""}
</div>`
: ""
}
${
isMenuVisible && !readonly && !renaming && !column.collapsed
? `<div class="wx-menu" data-menu-id=${column.id}>
<i class="wxi-dots-v"></i>
</div>`
: ""
}`;
}
function customCollapsedColumn({ column, columnState }) {
return `<div class="wx-collapsed-label">
<div class="wx-label-text">${escapeHTML(column.label)} (${
columnState?.cardsCount
})</div>
</div>`;
}
new Kanban("#root", {
columns,
cards,
columnShape: {
headerTemplate: template(props =>
columnHeaderTemplate(props)
),
collapsedTemplate: template(props =>
customCollapsedColumn(props)
),
},
});<!-- component container -->
<div style="height: 100%; width: 100%" id="root"></div>
<!-- styles for header template -->
<style>
.wx-header .wx-column {
padding: 12px
}
.wx-menu,
.wx-collapse-icon,
.wxi-angle-left {
display: flex;
cursor: pointer;
font-size: var(--wx-font-size-md);
color: var(--wx-color-font-alt);
}
.wx-collapsed-label {
writing-mode: tb-rl;
font-weight: 500;
font-size: var(--wx-font-size);
margin: 12px 0;
display: flex;
align-items: center;
width: 100%;
z-index: 5;
}
.wx-label-text {
white-space: nowrap;
transform: rotate(180deg);
z-index: 5;
pointer-events: none;
}
.wx-label {
display: flex;
align-items: center;
font-weight: var(--wx-font-weight-md);
font-size: var(--wx-font-size);
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
height: 100%;
margin-left: 4px;
}
</style>
<script>
const columns = [
{
label: "Backlog",
id: "backlog",
},
{
label: "In progress",
id: "inprogress",
},
{
label: "Testing",
id: "testing",
},
{
label: "Done",
id: "done",
},
];
const cards = [
{
label: "Integration with Angular/React",
column: "backlog",
},
{
label: "Archive the cards/boards ",
column: "backlog",
},
{
label: "Searching and filtering",
column: "backlog",
},
{
label: "Set the tasks priorities",
column: "inprogress",
},
{
label: "Custom icons",
column: "inprogress",
},
{
label: "Integration with Gantt",
column: "inprogress",
},
{
label: "Drag and drop",
column: "testing",
},
{
label: "Adding images",
column: "testing",
},
{
label: "Create cards and lists from the UI and from code",
column: "done",
},
{
label: "Draw swimlanes",
column: "done",
},
{
label: "Progress bar",
column: "done",
},
];
</script>The code defines two template functions: columnHeaderTemplate renders the expanded header with a collapse icon, label with card count and limit display, and a menu icon; customCollapsedColumn renders a vertical label for collapsed columns. Both are passed to columnShape.headerTemplate and columnShape.collapsedTemplate wrapped in the template() helper. The template receives column, columnState (with cardsCount and totalLimit), readonly, isMenuVisible, and renaming flags, plus uses data-action attributes to hook into built-in Kanban actions.
Solution overview
- Create a header template function that receives
{ column, columnState, readonly, isMenuVisible, renaming } - Create a collapsed template function that receives
{ column, columnState } - Pass them via
columnShape: { headerTemplate: template(fn), collapsedTemplate: template(fn) } - Use
data-action="collapse"anddata-action="rename"on elements to bind built-in Kanban behaviors - Use
data-menu-id={column.id}to enable the context menu
Key points
template()wrapper is required: Always wrap template functions withkanban.template()before passing them tocolumnShapedata-actionattributes drive interaction: The Kanban listens fordata-action="collapse",data-action="rename", anddata-menu-idon template elements. Without these, built-in features won't triggercolumnStateprovides live data:cardsCountandtotalLimitupdate automatically as cards move. No manual tracking needed- HTML escaping: Always escape user-provided content (like
column.label) in templates to prevent XSS
API reference
- columnShape: Column appearance configuration including
headerTemplateandcollapsedTemplate - template: Wraps a function for use as a reactive template