Client core API (TypeScript)
@elyra/datagrid-client-core is the headless, framework-agnostic engine. The
Svelte and Vue clients wrap it; you can also use it directly with any framework.
import { createGrid } from '@elyra/datagrid-client-core';
const grid = createGrid(options);
grid.subscribe((state) => { /* re-render */ });
GridOptions
interface GridOptions {
columns: ColumnDef[];
fetch: (request: GridRequest) => Promise<GridResponse>;
key?: string; // key column, always fetched (default 'id')
rowId?: (row) => RowId; // default: row[key]
// features — false | true | { ...options }
header?: Feature<HeaderOptions>; // default on
sorting?: Feature<SortingOptions>; // default on; { multi }
paging?: Feature<PagingOptions>; // default on (paged, 20)
filtering?: Feature<FilteringOptions>; // default on; { facets, row, builder }
search?: Feature<SearchOptions>; // default off; { mode, fields, vectorField }
selection?: Feature<SelectionOptions>; // default off; { mode, checkbox }
grouping?: Feature<GroupingOptions>; // default off; { rollup, aggregates, detailRows, detailLimit }
columnOps?: Feature<ColumnOpsOptions>; // default off; { reorder, resize, freeze, visibility }
masterDetail?: MasterDetailOptions; // { load, initiallyExpanded }
editing?: EditingOptions; // { mode, trigger, batch, mutate } (mutate required)
columnVirtual?: boolean | { defaultWidth?: number; overscan?: number };
tree?: { parentField: string; rootValue?: unknown; hasChildrenField?: string };
headerGroups?: { header: string; columns: string[] }[];
aggregates?: AggregateSpec[]; // footer aggregates
meta?: MetaFlag[]; // extra opt-ins
autoFetch?: boolean; // default true
messages?: Partial<Messages>; // i18n overrides
exportUrl?: string; // POST target for export
persistKey?: string; // localStorage persistence
initialData?: GridResponse; // server-seeded first page (skips initial fetch)
initial?: { sort?; filter?; group?; viewport? };
}
Feature rule
Core display features (header, sorting, paging, filtering) default on.
Interaction features (selection, grouping, search, columnOps,
masterDetail, editing, columnVirtual) default off. false always forces
off; true uses defaults; an object gives full control.
Feature option shapes
interface FilteringOptions { facets?: boolean; row?: boolean; builder?: boolean } // default true, except builder
interface GroupingOptions {
rollup?: boolean; aggregates?: AggregateSpec[];
detailRows?: boolean; // expand an innermost group to reveal its rows (lazy)
detailLimit?: number; // max detail rows per expanded group (default 200)
}
interface EditingOptions {
mode?: 'inline' | 'modal' | 'slideover' | 'incell';
trigger?: 'cell' | 'row' | 'button';
batch?: boolean; // incell: accumulate dirty edits, persist via saveBatch()
mutate: (m: GridMutation) => Promise<GridMutationResult>; // required
}
// ColumnDef.frozen: boolean | 'left' | 'right' (true = left)
PagingOptions
{ mode?: 'paged' | 'virtual'; pageSize?: number; // default 20
pageSizeOptions?: number[]; // [20,50,100,200]
allowAll?: boolean; maxAll?: number; // "All" (capped 1000)
rowHeight?: number; overscan?: number } // virtual scroll
The Grid object
interface Grid {
readonly features: ResolvedFeatures;
getState(): GridState;
subscribe(listener: (state: GridState) => void): () => void;
refresh(): Promise<void>;
// sorting
toggleSort(field, additive?); setSort(sort);
// filtering
setFilter(filter | null); setSearch(query);
setColumnFilterValue(field, value); setColumnFilterOp(field, op);
clearColumnFilter(field); columnFilterOf(field);
loadFacet(field, top?); isFacetLoading(field);
// grouping
groupBy(field); ungroup(field); setGroups(fields);
toggleGroup(path); isGroupCollapsed(path);
// selection
toggleSelect(id); isSelected(id); selectAllOnPage(); clearSelection(); selectedIds();
// paging
setViewport(skip, take); setPageSize(size | 'all'); goToPage(page); onScroll(scrollTop, viewportHeight); pageCount();
// grouping detail-rows (grouping.detailRows)
toggleGroupDetail(path); isGroupDetailExpanded(path); groupDetailOf(path); isGroupDetailLoading(path);
// master-detail
toggleExpand(id); isExpanded(id); detailOf(id);
// editing (inline/modal/slideover/incell)
beginEdit(id, field?); beginCreate(); setDraft(field, value);
cancelEdit(); commitEdit(); removeRow(id); isEditing(id, field?);
// batch / in-cell editing (editing.mode 'incell')
commitCell(); isDirty(id, field?); dirtyValueOf(id, field); cellValue(row, field);
dirtyRowCount(); saveBatch(); cancelBatch();
// columns
setColumnVisible(field, visible); moveColumn(field, toIndex);
moveColumnLeft(field); moveColumnRight(field); resizeColumn(field, width); freezeColumn(field, frozen);
// clipboard + pinning + tree + column virtualization
pasteAt(text); togglePinRow(id); isPinned(id);
toggleTreeNode(id); isTreeExpanded(id); onScrollX(scrollLeft, viewportWidth);
// keyboard / cell selection
setActiveCell(r, c, extend?); isActiveCell(r, c); inSelectionRange(r, c); copySelection();
moveActive(key, extend?, opts?: { ctrl?: boolean; pageRows?: number });
// key: Arrow*/Home/End/PageUp/PageDown; ctrl+Home/End => first/last cell of grid
// export
exportData();
destroy();
}
GridState
interface GridState {
columns: ResolvedColumn[];
sort: SortSpec[];
filter: FilterGroup | null;
columnFilters: Record<string, ColumnFilter>;
search: { query: string } | null;
group: string[];
collapsedGroups: string[];
selection: { mode; ids: Set<RowId>; allPagesSelected };
viewport: { skip; take };
expanded: Set<RowId>;
editing: EditingState | null;
activeCell: CellRef | null; anchor: CellRef | null;
pinnedRows: RowId[];
treeExpanded: RowId[];
colWindow: ColWindow | null;
dirty: Record<string, Record<string, unknown>>; // unsaved batch/in-cell edits (rowId => field=>value)
expandedGroups: string[]; // innermost-group paths showing detail rows
groupDetail: Record<string, Row[]>; // lazily loaded detail rows per group path
groupDetailLoading: string[];
data: { rows; total; groups; aggregates; facets; facetsLoading; loading; error };
}
Helpers
import { pageItems, computeWindow, computeColumnWindow,
operatorsForType, defaultOpForType, headerBandRow,
resolveMessages, defaultMessages,
// advanced filter-builder tree helpers (immutable, path-addressed)
newGroup, newCondition, addCondition, addGroup, setLogic,
updateCondition, removeNode, isGroup, isEmptyFilter, countConditions }
from '@elyra/datagrid-client-core';
pageItems(current, totalPages)— numbered pager items with ellipses.computeWindow(input)— virtual row window from scroll position.computeColumnWindow(widths, scrollLeft, viewportWidth, overscan)— column window.operatorsForType(type)/defaultOpForType(type)— filter operators.headerBandRow(cols, groups)— multi-column-header banner cells.resolveMessages(partial)— merge i18n overrides onto English defaults.
Filter-builder helpers
Immutable helpers for building nested AND/OR filter trees (used by the
advanced filter builder; edits are addressed by a path of child indices from
the root group):
newGroup(logic?) // { logic, filters: [] }
newCondition(field, op?, value?) // a leaf condition
addCondition(root, groupPath, cond) // -> new tree
addGroup(root, groupPath, logic?) // -> new tree
setLogic(root, groupPath, logic) // AND <-> OR
updateCondition(root, path, patch) // patch a leaf
removeNode(root, path) // drop a node
isGroup(node) · isEmptyFilter(node) · countConditions(node)
Build a tree and hand it to grid.setFilter(tree).