Grid
Explore filtering, selection, bulk edits, row actions, and expandable details.
Live TypeScript example
Try the component here, then use the source below in your application.
- JavaScript
- 347.2 KiB
- Component CSS
- 5.3 KiB
- Shared theme CSS
- 3.8 KiBonce per application
How sizes are measured
The JavaScript figure includes this component’s required helpers. CSS includes its styling dependencies. Each entry is bundled separately for ES2022, minified, then compressed with gzip level 9. Your bundler may share helpers across components. Images, fonts, examples and application code are excluded.
Before compression: JavaScript 1232.9 KiB; component CSS 29.2 KiB. These figures describe browser assets, not the complete package download.
View all component measurements →Edit a cell, then save. This example stores changes in this browser.
import '@blukavantui/web/theme.css'
import '@blukavantui/web/grid.css';
import { createGrid } from "@blukavantui/web/grid";
import "@blukavantui/web/grid.css";
interface Customer {
Id: number;
Name: string;
Seats: number;
}
export function mount(host: HTMLElement) {
const toolbar = document.createElement("div"),
save = document.createElement("button"),
output = document.createElement("p");
output.setAttribute("role", "status");
save.textContent = "Save changes";
save.type = "button";
toolbar.append(save, output);
host.append(toolbar);
const grid = createGrid<Customer>(host, {
RowKeyField: "Id",
Columns: [
{ Field: "Name", Header: "Customer", IsEditable: true, Flex: 1 },
{ Field: "Seats", Type: "Number", IsEditable: true },
],
Rows: [
{ Id: 1, Name: "Atlas Labs", Seats: 12 },
{ Id: 2, Name: "Northstar", Seats: 24 },
],
Config: {
Height: "360px",
SelectionMode: "Multiple",
EnablePagination: true,
PageSize: 10,
},
Events: {
OnEditStateChanged: (state) => {
save.disabled = !state.HasChanges || state.IsSaving;
},
},
});
save.onclick = async () => {
const request = await grid.beginSave();
if (!request.SaveToken) return;
try {
// Replace this local persistence with a validated backend request returning canonical rows.
localStorage.setItem("bluui-starter-grid", JSON.stringify(request.Rows));
grid.completeSave(request.SaveToken, request.Rows);
output.textContent = "Saved in this browser.";
} catch {
grid.failSave(request.SaveToken, [
{
RowId: "",
Field: "",
Code: "SAVE_FAILED",
Message: "Could not save. Retry your changes.",
},
]);
}
};
return {
destroy() {
grid.destroy();
toolbar.remove();
},
};
}
const instance = mount(document.getElementById('example')!)
// When this page or framework component is removed:
// instance.destroy()
Install the library and add the host element
npm install https://blukavantui.blutekmedia.com/downloads/blukavantui-web-0.6.3.tgz<div id="example"></div>This example uses the downloadable @blukavantui/web package. Your application handles persistence and authentication through its typed callbacks. The starter ZIP includes this same example.
createGrid
Pass callbacks inside options.Events. Use typed rows and columns; R is your application’s row type. For saving, await beginSave(), persist the rows, then call completeSave() or failSave() with that save token.
import { createGrid } from '@blukavantui/web/grid';
import '@blukavantui/web/grid.css';Load @blukavantui/web/theme.css once in your app shell.createGrid<R extends object>(host: HTMLElement, options: GridOptions<R>)Reference for @blukavantui/web 0.6.3. Required and optional follow the shipped TypeScript declarations; optional does not imply a particular default. Pass typed arrays and objects directly where shown.
Options
7| Name | Type / requirement | Usage |
|---|---|---|
Columns | GridColumn<R>[]Required | Column definitions. Field names must belong to your row type R. |
Rows | R[]Optional | Rows currently supplied by your application. |
RowKeyField | GridField<R>Required | The field containing a stable, unique key for every row. |
Mode | "Client" | "Infinite"Optional | Client uses supplied rows. Infinite requests row ranges through OnDataRequested. |
Config | GridConfigOptional | Grid layout, selection, editing, pagination and presentation settings. |
SearchText | stringOptional | Initial text search. Call setSearch() to change it after mounting. |
Events | GridEvents<R>Optional | Grid callbacks belong in this options object, rather than a third factory argument. |
Callbacks
11| Name | Type / requirement | Usage |
|---|---|---|
OnRowClick | (args_0: { GridId: string; Row: R; RowId: string; }) => void | Promise<void>Optional | Reports the clicked row and its key. |
OnRowDoubleClick | (args_0: { GridId: string; Row: R; RowId: string; }) => void | Promise<void>Optional | Reports a double-click on a row. |
OnSelectionChanged | (args_0: { GridId: string; Rows: R[]; }) => void | Promise<void>Optional | Reports the selected row objects. |
OnCellValueChanged | (args_0: { GridId: string; Row: R; RowId: string; Field: Extract<keyof R, string>; OldValue: unknown; NewValue: unknown; }) => void | Promise<void>Optional | Reports a changed cell, including old and new values. |
OnBatchValueChanged | (args_0: { GridId: string; Changes: { Row: R; RowId: string; Field: Extract<keyof R, string>; OldValue: unknown; NewValue: unknown; }[]; }) => void | Promise<void>Optional | One notification for all actual changes made by applyRowValues. |
OnEditStateChanged | (args_0: GridEditState & { GridId: string; }) => void | Promise<void>Optional | Reports changes to dirty, editing and saving state. |
OnDataError | (args_0: { GridId: string; Code: string; Message: string; }) => void | Promise<void>Optional | Reports a grid data error with a code and message. |
OnDataRequested | (args_0: GridDataRequest) => void | Promise<void>Optional | Requests a range of rows in Infinite mode. Complete or fail the matching RequestId. |
OnRowAction | (args_0: { GridId: string; ActionKey: string; RowId: string; Row: R; }) => void | Promise<void>Optional | Reports the action key and the row it applies to. |
OnBulkAction | (args_0: { GridId: string; ActionKey: string; RowIds: string[]; Rows: R[]; }) => void | Promise<void>Optional | Reports the action key and selected rows. |
OnRowExpansionChanged | (args_0: { GridId: string; RowId: string; IsExpanded: boolean; Row: R; }) => void | Promise<void>Optional | Reports whether a row detail view is expanded. |
Instance methods & properties
20| Name | Signature / type | Usage |
|---|---|---|
element | HTMLElement | The root DOM element owned by this instance. |
update | (patch: Partial<Pick<GridOptions<R>, "Columns" | "Rows" | "Config">>) => void | Apply a partial options update to this instance. |
setSearch | (text: string) => void | Apply a new text search. |
setData | (rows: R[]) => void | Replace the supplied row data. |
getSelectedRows | () => R[] | Return the selected row objects. |
clearSelection | () => void | Clear the current row selection. |
selectPage | () => void | Select rows on the current page. |
applyRowValues | (ids: (string | number)[], values: Partial<R>, options?: { EmitCellEvents?: boolean; }) => GridEditState | Stage values on the specified rows. Optional EmitCellEvents controls individual change notifications. |
beginSave | () => Promise<GridSaveRequest<R>> | Begin a save and obtain the token and changed rows. Await your application’s persistence before acknowledging success. |
completeSave | (token: string, rows: R[]) => R[] | Acknowledge a successful save with its matching token and canonical rows. |
failSave | (token: string, errors?: GridSaveError[]) => GridEditState | Reject the matching save; pending edits are retained. |
cancelChanges | () => Promise<GridEditState> | Discard pending changes. |
getEditState | () => GridEditState | Read dirty, editing and saving state. |
completeDataRequest | (requestId: string, rows: R[], total: number) => boolean | Supply the rows and total count for a matching data request. |
failDataRequest | (requestId: string, message: string) => boolean | Report a failure for a matching data request. |
retryLoading | () => void | Retry a failed data load. |
setColumnVisible | (field: Extract<keyof R, string>, visible: boolean) => void | Show or hide one column. |
setRowExpanded | (rowId: string, expanded: boolean) => void | Open or close a row’s detail view. |
exportCsv | (options?: { FileName?: string; OnlySelected?: boolean; }) => void | Export rows as CSV; optionally limit the export to selected rows. |
destroy | () => void | Dispose the instance and its listeners when the view is removed. |
Related data types
Expand a type for its fields and allowed values.
Callback
type Callback<T extends unknown[] = []> = (...args: T) => void | Promise<void>;ComponentColor
type ComponentColor = typeof componentColors[number];GridAction
interface GridAction {
Key: string;
Label: string;
Icon?: string;
IsDisabled?: boolean;
DisabledField?: string;
}GridChange
interface GridChange {
RowId: string;
OriginalRowJson: string;
RowJson: string;
ChangedFieldsJson: string;
}GridColumn
interface GridColumn<R extends object> {
Field: GridField<R>;
Header?: string;
Type?: "Text" | "Number" | "Currency" | "Date" | "DateTime" | "Boolean";
Width?: number;
MinWidth?: number;
Flex?: number;
IsSortable?: boolean;
IsFilterable?: boolean;
IsResizable?: boolean;
IsHidden?: boolean;
IsPinned?: boolean;
IsEditable?: boolean;
IsRequired?: boolean;
MaxLength?: number;
DecimalPlaces?: number;
HasMinValue?: boolean;
MinValue?: number;
HasMaxValue?: boolean;
MaxValue?: number;
SelectOptions?: {
Value: string;
Label: string;
}[];
StyleRules?: GridStyleRule[];
Renderer?: "Badge" | "Progress" | "Action";
ActionKey?: string;
ActionLabel?: string;
Color?: ComponentColor;
ColorField?: GridField<R>;
}GridConfig
interface GridConfig {
Height?: string;
RowHeight?: number;
SelectionMode?: "None" | "Single" | "Multiple";
IsLoading?: boolean;
ExtendedClass?: string;
Locale?: string;
CurrencyCode?: string;
TimeZone?: string;
IsReadOnly?: boolean;
ShowEditToolbar?: boolean;
EnablePagination?: boolean;
PageSize?: number;
CacheBlockSize?: number;
MaxBlocksInCache?: number;
DataRequestTimeout?: number;
ShowFloatingFilters?: boolean;
EnableRowDetails?: boolean;
DetailHeight?: number;
DetailTitleField?: string;
RowActions?: GridAction[];
BulkActions?: GridAction[];
DetailFields?: {
Field: string;
Label?: string;
}[];
MaxFilterConditions?: number;
RowStyleRules?: GridStyleRule[];
SummaryMode?: "None" | "Filtered" | "All" | "Server";
SummaryLabel?: string;
SummaryLabelField?: string;
SummaryFields?: {
Field: string;
Operation: "Sum" | "Average" | "Min" | "Max" | "Count";
}[];
}GridDataRequest
interface GridDataRequest {
GridId: string;
RequestId: string;
StartRow: number;
EndRow: number;
Sort: {
Field: string;
Direction: "asc" | "desc";
}[];
Filter: Record<string, unknown>;
SearchText: string;
}GridEditState
interface GridEditState {
HasChanges: boolean;
ChangedRowCount: number;
ChangedCellCount: number;
IsEditing: boolean;
IsSaving: boolean;
}GridField
type GridField<R> = Extract<keyof R, string>;GridInstance
interface GridInstance<R extends object> {
readonly element: HTMLElement;
update(patch: Partial<Pick<GridOptions<R>, "Columns" | "Rows" | "Config">>): void;
setSearch(text: string): void;
setData(rows: R[]): void;
getSelectedRows(): R[];
clearSelection(): void;
selectPage(): void;
applyRowValues(ids: (string | number)[], values: Partial<R>, options?: {
/** Defaults to true for compatibility. False emits only the batch change event. */
EmitCellEvents?: boolean;
}): GridEditState;
beginSave(): Promise<GridSaveRequest<R>>;
completeSave(token: string, rows: R[]): R[];
failSave(token: string, errors?: GridSaveError[]): GridEditState;
cancelChanges(): Promise<GridEditState>;
getEditState(): GridEditState;
completeDataRequest(requestId: string, rows: R[], total: number): boolean;
failDataRequest(requestId: string, message: string): boolean;
retryLoading(): void;
setColumnVisible(field: GridField<R>, visible: boolean): void;
setRowExpanded(rowId: string, expanded: boolean): void;
exportCsv(options?: {
FileName?: string;
OnlySelected?: boolean;
}): void;
destroy(): void;
}GridSaveError
interface GridSaveError {
RowId: string;
Field: string;
Code: string;
Message: string;
}GridSaveRequest
interface GridSaveRequest<R> {
SaveToken: string;
Rows: R[];
Changes: GridChange[];
}GridStyleRule
interface GridStyleRule {
Field?: string;
Operator: "equals" | "notEqual" | "greaterThan" | "greaterThanOrEqual" | "lessThan" | "lessThanOrEqual" | "inRange" | "blank" | "notBlank" | "contains" | "notContains" | "startsWith" | "endsWith";
Value?: string;
ValueTo?: string;
Color?: ComponentColor;
}Use these inputs, events, actions and structures in Service Studio. Names and data bindings are specific to the native Blocks.
Grid Basic is planned for the free Community edition. This page demonstrates the full commercial Grid, including editing and bulk saving. View Community scope →
Open OutSystems showcase ↗- Web runtime
- Supported
- TypeScript
- Supported
- OutSystems
- Supported
Statuses describe the component’s rendered code and interactions. Supply accessible content and follow the component guidance when integrating it.
Accessibility guidance →Purpose and use
Use Grid for structured records that people compare, filter, and edit. Keep drafts visible until the whole save succeeds.
Keyboard design guidance
Use the grid’s arrow-key navigation, Enter to edit, and Escape to cancel an editor. Label toolbar controls and show save errors beside retained drafts.
See the support status above for review coverage and any limitations.
In your application
Provide useful labels, preserve visible focus, and test the component with your actual content. Use text alongside status colors and check contrast in each state.
Events0No events yet.
Interact with an example to see its events.