DHTMLX Kanban. Keep sort order example
Sorting cards within columns is useful for prioritization, but by default the sort order resets when cards are added or moved. Persistent sorting keeps the chosen order intact even as the board changes, automatically placing new or moved cards in the correct position.
Live example
const { Kanban, Toolbar, defaultEditorShape } = kanban;
const board = new Kanban("#root", {
columns,
cards,
rows,
rowKey: "type",
cardShape,
editorShape: defaultEditorShape,
});
new Toolbar("#toolbar", { api: board.api });
setTimeout(() => board.api.exec("set-sort", { by: "label", preserve: true }));<!-- 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", value: 1 },
{ id: 2, color: "#FFC975", label: "Medium", value: 2 },
{ id: 3, color: "#65D3B3", label: "Low", value: 3 },
],
},
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",
start_date: new Date("01/01/2021"),
},
{
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 calls board.api.exec("set-sort", { by: "label", preserve: true }) after initialization (wrapped in setTimeout to ensure the board is rendered). The preserve: true flag makes the sort persistent. Any new cards added to the board or cards moved between columns are automatically sorted by label within their column. Without preserve, sorting is a one-time operation.
Solution overview
- Initialize the board normally
- Call
board.api.exec("set-sort", { by: "label", preserve: true })to apply persistent sorting - Use
setTimeoutto ensure the board is fully rendered before applying the sort
Key points
preserve: trueis the key: Without it,set-sortonly sorts once. New or moved cards won't respect the order- Sort by any card field: The
byparameter accepts any card property name:"label","start_date","priority", etc. - Drag reordering is overridden: With persistent sorting active, manually dragging cards to reorder within a column will be overridden by the sort. The card snaps back to its sorted position
setTimeouttiming: The sort must be applied after the board renders. Calling it synchronously during initialization may not work
API reference
- api.exec: Triggers internal events including
set-sort