Save and Restore Board State
Choose what you want to remember: card data, column order, collapsed presentation or the current view. Your application chooses storage and permissions; saving locally is not the same as persisting changes on a server.
Save and restore your board
This app saves cards and column order in the example’s memory.
Try it: Save this board, change it, then restore the saved copy.
What to notice: The original cards and column order return. Reset clears the saved copy.
TypeScript source
Install the packages from Getting Started, then use this source in your app.
import type { KanbanPlugin } from '@revolist/kanban';import type { WorkCard } from './first-board';
export function showHighPriority(kanban: KanbanPlugin<WorkCard>) { kanban.setFilter({ predicate: card => card.priority === 'high' });}export function searchResearch(kanban: KanbanPlugin<WorkCard>) { kanban.setFilter({ query: 'research', fields: ['title'] });}export function clearFilters(kanban: KanbanPlugin<WorkCard>) { kanban.setFilter(); }
// An app-owned snapshot of serializable data, not a Kanban remote-store API.export function captureBoard(kanban: KanbanPlugin<WorkCard>) { return { cards: kanban.getCards().map(card => ({ ...card })), columns: [...kanban.getColumnOrder()], collapsed: [...kanban.getCollapsedColumnProps()], selected: [...kanban.getSelectedCardIds()] };}export async function restoreBoard(grid: HTMLRevoGridElement, kanban: KanbanPlugin<WorkCard>, saved: ReturnType<typeof captureBoard>) { grid.source = saved.cards.map(card => ({ ...card })); await new Promise<void>(resolve => requestAnimationFrame(() => requestAnimationFrame(() => resolve()))); kanban.setColumnOrder(saved.columns); for (const prop of kanban.getColumnOrder()) kanban.setColumnCollapsed(prop, saved.collapsed.includes(prop)); kanban.setSelectedCardIds(saved.selected);}// Persist JSON.stringify(captureBoard(kanban)) in your application's storage.// Restore only data validated by your application; the live example stays in memory.import { defineCustomElements } from '@revolist/revogrid/loader';import { KanbanPlugin, type KanbanConfig } from '@revolist/kanban';import '@revolist/revogrid-pro/styles.css';import '@revolist/kanban/styles.css';
export interface WorkCard { id: string; title: string; status: string; order: number; description?: string; team?: string; owner?: string; priority?: string; tags?: string[]; progress?: number; startDate?: string; endDate?: string;}export const demoCards: WorkCard[] = [ { id: 'task-1', title: 'Research customer needs', description: 'Collect feedback for the next release.', status: 'todo', team: 'product', owner: 'Ana', priority: 'normal', order: 1000 }, { id: 'task-2', title: 'Build onboarding', description: 'Make the first session useful.', status: 'doing', team: 'product', owner: 'Mia', priority: 'high', order: 1000 }, { id: 'task-3', title: 'Improve API errors', description: 'Return actionable validation messages.', status: 'todo', team: 'platform', owner: 'Rui', priority: 'normal', order: 2000 }, { id: 'task-4', title: 'Release checklist', description: 'Ready for the next deployment.', status: 'done', team: 'platform', owner: 'Sam', priority: 'normal', order: 1000 },];export const boardConfig: KanbanConfig<WorkCard> = { columns: [{ prop: 'todo', name: 'To do', size: 210 }, { prop: 'doing', name: 'In progress', size: 210 }, { prop: 'done', name: 'Done', size: 210 }], card: { titleField: 'title' }, cardRowHeight: 88, addCard: false, swimlaneColumn: false,};
export async function configureBoard( grid: HTMLRevoGridElement, config: KanbanConfig<WorkCard> = boardConfig, cards: readonly WorkCard[] = demoCards, extraPlugins: HTMLRevoGridElement['plugins'] = [],) { await defineCustomElements(); grid.plugins = [KanbanPlugin, ...extraPlugins]; // The packaged editor and history install automatically. grid.columns = [{ prop: 'title', name: 'Title' }, { prop: 'status', name: 'Status' }, { prop: 'owner', name: 'Owner' }]; // Cached remote data can hydrate immediately: finish initial grid setup first. grid.kanban = config.remote ? { ...config, remote: false } : config; grid.source = cards.map(card => ({ ...card })); await grid.componentOnReady(); const plugins = await grid.getPlugins(); const kanban = plugins.find((plugin): plugin is KanbanPlugin<WorkCard> => plugin instanceof KanbanPlugin); if (!kanban) throw new Error('Kanban could not start.'); if (config.remote) grid.kanban = config; return kanban;}
// Give your container a width and mount once after it exists in the DOM.export async function createKanbanBoard(container: HTMLElement) { await defineCustomElements(); const grid = document.createElement('revo-grid'); grid.style.cssText = 'display:block;width:100%;height:400px'; container.append(grid); try { const kanban = await configureBoard(grid); return { grid, kanban, destroy() { grid.remove(); } }; } catch (error) { grid.remove(); throw error; }}Try it: save the example, change its cards or layout, then restore. The example keeps its saved copy in memory; Reset discards it.
Save plain state
Section titled “Save plain state”For a ready Kanban plugin:
const saved = { cards: kanban.getCards(), columnOrder: kanban.getColumnOrder(), collapsedColumns: kanban.getCollapsedColumnProps(), collapsedLanes: kanban.getCollapsedSwimlaneIds(), laneLabelsCollapsed: kanban.getSwimlaneColumnCollapsed(),};localStorage.setItem('my-board', JSON.stringify(saved));This example assumes your application cards are JSON-safe. Rehydrate special values, validate stored data and recreate callback functions according to your application’s schema. Do not serialize projected rows from getProjection() as if they were application cards.
Restore deliberately
Section titled “Restore deliberately”Load saved card records into grid.source, then reapply the presentation you chose to save. Use setColumnOrder, setColumnCollapsed and setSwimlaneColumnCollapsed for their respective presentation state. To restore lane collapse, provide explicit swimlanes definitions with the saved collapsed flags.
Replacing source data clears local Kanban history. Saved data may be stale; reconcile it with your backend before replacing a newer server board.
Persistence ownership
Section titled “Persistence ownership”Use the optional async approval and persistence adapter for atomic versioned writes, precise rollback, retries and server-approved history. It captures canonical CRUD, moves and history once; do not add a second save listener.
For manually managed integrations without the adapter, kanbancardmove exposes
changedCards, including every rank-rebalanced neighbor. Persist them atomically.
beforekanbancardmove remains a synchronous veto; use approveMove and
moveCardsAsync when approval needs to await a server.
Next steps
Section titled “Next steps”Continue with server-side saving, managed persistence or board/table views. See the Kanban API for exact types and signatures.