@alaarab/ogrid-mcp 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -0
- package/bundled-docs/api/README.md +94 -0
- package/bundled-docs/api/column-def.mdx +379 -0
- package/bundled-docs/api/components-column-chooser.mdx +310 -0
- package/bundled-docs/api/components-column-header-filter.mdx +363 -0
- package/bundled-docs/api/components-datagrid-table.mdx +316 -0
- package/bundled-docs/api/components-pagination-controls.mdx +344 -0
- package/bundled-docs/api/components-sidebar.mdx +427 -0
- package/bundled-docs/api/components-status-bar.mdx +309 -0
- package/bundled-docs/api/grid-api.mdx +299 -0
- package/bundled-docs/api/js-api.mdx +198 -0
- package/bundled-docs/api/ogrid-props.mdx +244 -0
- package/bundled-docs/api/types.mdx +640 -0
- package/bundled-docs/features/cell-references.mdx +225 -0
- package/bundled-docs/features/column-chooser.mdx +279 -0
- package/bundled-docs/features/column-groups.mdx +290 -0
- package/bundled-docs/features/column-pinning.mdx +282 -0
- package/bundled-docs/features/column-reordering.mdx +359 -0
- package/bundled-docs/features/column-types.mdx +181 -0
- package/bundled-docs/features/context-menu.mdx +216 -0
- package/bundled-docs/features/csv-export.mdx +227 -0
- package/bundled-docs/features/editing.mdx +377 -0
- package/bundled-docs/features/filtering.mdx +330 -0
- package/bundled-docs/features/formulas.mdx +381 -0
- package/bundled-docs/features/grid-api.mdx +311 -0
- package/bundled-docs/features/keyboard-navigation.mdx +236 -0
- package/bundled-docs/features/pagination.mdx +245 -0
- package/bundled-docs/features/performance.mdx +433 -0
- package/bundled-docs/features/row-selection.mdx +256 -0
- package/bundled-docs/features/server-side-data.mdx +291 -0
- package/bundled-docs/features/sidebar.mdx +234 -0
- package/bundled-docs/features/sorting.mdx +241 -0
- package/bundled-docs/features/spreadsheet-selection.mdx +201 -0
- package/bundled-docs/features/status-bar.mdx +205 -0
- package/bundled-docs/features/toolbar.mdx +284 -0
- package/bundled-docs/features/virtual-scrolling.mdx +624 -0
- package/bundled-docs/getting-started/installation.mdx +216 -0
- package/bundled-docs/getting-started/overview.mdx +151 -0
- package/bundled-docs/getting-started/quick-start.mdx +425 -0
- package/bundled-docs/getting-started/vanilla-js.mdx +191 -0
- package/bundled-docs/guides/accessibility.mdx +550 -0
- package/bundled-docs/guides/controlled-vs-uncontrolled.mdx +153 -0
- package/bundled-docs/guides/custom-cell-editors.mdx +201 -0
- package/bundled-docs/guides/framework-showcase.mdx +200 -0
- package/bundled-docs/guides/mcp-live-testing.mdx +291 -0
- package/bundled-docs/guides/mcp.mdx +172 -0
- package/bundled-docs/guides/migration-from-ag-grid.mdx +223 -0
- package/bundled-docs/guides/theming.mdx +211 -0
- package/dist/esm/bridge-client.d.ts +87 -0
- package/dist/esm/bridge-client.js +162 -0
- package/dist/esm/index.js +1060 -0
- package/package.json +43 -0
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 3
|
|
3
|
+
title: Quick Start
|
|
4
|
+
description: Build a fully functional data grid in minutes
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# Quick Start
|
|
9
|
+
|
|
10
|
+
Build a sortable, filterable, editable data grid in under 50 lines.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
<Tabs groupId="framework">
|
|
15
|
+
<TabItem value="react" label="React" default>
|
|
16
|
+
|
|
17
|
+
<Tabs groupId="react-ui">
|
|
18
|
+
<TabItem value="radix" label="Radix (Default)" default>
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install @alaarab/ogrid-react-radix
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
</TabItem>
|
|
25
|
+
<TabItem value="fluent" label="Fluent UI">
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @alaarab/ogrid-react-fluent @fluentui/react-components
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
</TabItem>
|
|
32
|
+
<TabItem value="material" label="Material UI">
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install @alaarab/ogrid-react-material @mui/material @emotion/react @emotion/styled
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
</TabItem>
|
|
39
|
+
</Tabs>
|
|
40
|
+
|
|
41
|
+
</TabItem>
|
|
42
|
+
<TabItem value="angular" label="Angular">
|
|
43
|
+
|
|
44
|
+
<Tabs groupId="angular-ui">
|
|
45
|
+
<TabItem value="angular-material" label="Angular Material" default>
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm install @alaarab/ogrid-angular-material @angular/material @angular/cdk
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
</TabItem>
|
|
52
|
+
<TabItem value="angular-primeng" label="PrimeNG">
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npm install @alaarab/ogrid-angular-primeng primeng
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
</TabItem>
|
|
59
|
+
</Tabs>
|
|
60
|
+
|
|
61
|
+
</TabItem>
|
|
62
|
+
<TabItem value="vue" label="Vue">
|
|
63
|
+
|
|
64
|
+
<Tabs groupId="vue-ui">
|
|
65
|
+
<TabItem value="vue-vuetify" label="Vuetify" default>
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npm install @alaarab/ogrid-vue-vuetify vuetify
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
</TabItem>
|
|
72
|
+
<TabItem value="vue-primevue" label="PrimeVue">
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
npm install @alaarab/ogrid-vue-primevue primevue
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
</TabItem>
|
|
79
|
+
</Tabs>
|
|
80
|
+
|
|
81
|
+
</TabItem>
|
|
82
|
+
<TabItem value="js" label="Vanilla JS">
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
npm install @alaarab/ogrid-js
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
</TabItem>
|
|
89
|
+
</Tabs>
|
|
90
|
+
|
|
91
|
+
## Full Example
|
|
92
|
+
|
|
93
|
+
<Tabs groupId="framework">
|
|
94
|
+
<TabItem value="react" label="React" default>
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
|
|
98
|
+
interface Employee {
|
|
99
|
+
id: number;
|
|
100
|
+
name: string;
|
|
101
|
+
department: string;
|
|
102
|
+
salary: number;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const data: Employee[] = [
|
|
106
|
+
{ id: 1, name: 'Alice Johnson', department: 'Engineering', salary: 95000 },
|
|
107
|
+
{ id: 2, name: 'Bob Smith', department: 'Marketing', salary: 72000 },
|
|
108
|
+
{ id: 3, name: 'Carol Williams', department: 'Engineering', salary: 110000 },
|
|
109
|
+
{ id: 4, name: 'David Brown', department: 'Sales', salary: 68000 },
|
|
110
|
+
{ id: 5, name: 'Eva Martinez', department: 'Marketing', salary: 78000 },
|
|
111
|
+
];
|
|
112
|
+
|
|
113
|
+
const columns: IColumnDef<Employee>[] = [
|
|
114
|
+
{ columnId: 'name', name: 'Name', sortable: true },
|
|
115
|
+
{
|
|
116
|
+
columnId: 'department',
|
|
117
|
+
name: 'Department',
|
|
118
|
+
sortable: true,
|
|
119
|
+
filterable: { type: 'multiSelect', options: ['Engineering', 'Marketing', 'Sales'] },
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
columnId: 'salary',
|
|
123
|
+
name: 'Salary',
|
|
124
|
+
type: 'numeric',
|
|
125
|
+
sortable: true,
|
|
126
|
+
editable: true,
|
|
127
|
+
valueFormatter: (value) =>
|
|
128
|
+
new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(value as number),
|
|
129
|
+
},
|
|
130
|
+
];
|
|
131
|
+
|
|
132
|
+
export default function App() {
|
|
133
|
+
return (
|
|
134
|
+
<OGrid<Employee>
|
|
135
|
+
columns={columns}
|
|
136
|
+
data={data}
|
|
137
|
+
getRowId={(row) => row.id}
|
|
138
|
+
defaultPageSize={10}
|
|
139
|
+
defaultSortBy="name"
|
|
140
|
+
statusBar
|
|
141
|
+
aria-label="Employee directory"
|
|
142
|
+
/>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
:::tip Switching UI libraries
|
|
148
|
+
The `OGrid` component has the same props across all React UI packages. To switch, just change the import:
|
|
149
|
+
|
|
150
|
+
- **Radix** (lightweight, default): `from '@alaarab/ogrid-react-radix'`
|
|
151
|
+
- **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'` — wrap in `<FluentProvider>`
|
|
152
|
+
- **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'` — wrap in `<ThemeProvider>`
|
|
153
|
+
:::
|
|
154
|
+
|
|
155
|
+
</TabItem>
|
|
156
|
+
<TabItem value="angular" label="Angular">
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
|
|
160
|
+
interface Employee {
|
|
161
|
+
id: number;
|
|
162
|
+
name: string;
|
|
163
|
+
department: string;
|
|
164
|
+
salary: number;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
@Component({
|
|
168
|
+
standalone: true,
|
|
169
|
+
imports: [OGridComponent],
|
|
170
|
+
template: `<ogrid [props]="gridProps" />`
|
|
171
|
+
})
|
|
172
|
+
export class EmployeeGridComponent {
|
|
173
|
+
private readonly data: Employee[] = [
|
|
174
|
+
{ id: 1, name: 'Alice Johnson', department: 'Engineering', salary: 95000 },
|
|
175
|
+
{ id: 2, name: 'Bob Smith', department: 'Marketing', salary: 72000 },
|
|
176
|
+
{ id: 3, name: 'Carol Williams', department: 'Engineering', salary: 110000 },
|
|
177
|
+
{ id: 4, name: 'David Brown', department: 'Sales', salary: 68000 },
|
|
178
|
+
{ id: 5, name: 'Eva Martinez', department: 'Marketing', salary: 78000 },
|
|
179
|
+
];
|
|
180
|
+
|
|
181
|
+
private readonly columns: IColumnDef<Employee>[] = [
|
|
182
|
+
{ columnId: 'name', name: 'Name', sortable: true },
|
|
183
|
+
{
|
|
184
|
+
columnId: 'department', name: 'Department', sortable: true,
|
|
185
|
+
filterable: { type: 'multiSelect', options: ['Engineering', 'Marketing', 'Sales'] },
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
columnId: 'salary', name: 'Salary', type: 'numeric', sortable: true, editable: true,
|
|
189
|
+
valueFormatter: (value) =>
|
|
190
|
+
new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(value as number),
|
|
191
|
+
},
|
|
192
|
+
];
|
|
193
|
+
|
|
194
|
+
gridProps = {
|
|
195
|
+
columns: this.columns,
|
|
196
|
+
data: this.data,
|
|
197
|
+
getRowId: (row: Employee) => row.id,
|
|
198
|
+
defaultPageSize: 10,
|
|
199
|
+
defaultSortBy: 'name',
|
|
200
|
+
statusBar: true,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
:::tip Switching UI libraries
|
|
206
|
+
Same component API across Angular packages. To switch, just change the import:
|
|
207
|
+
|
|
208
|
+
- **Radix (CDK)** (lightweight): `from '@alaarab/ogrid-angular-radix'`
|
|
209
|
+
- **Angular Material**: `from '@alaarab/ogrid-angular-material'`
|
|
210
|
+
- **PrimeNG**: `from '@alaarab/ogrid-angular-primeng'`
|
|
211
|
+
|
|
212
|
+
All components are standalone — no NgModule required.
|
|
213
|
+
:::
|
|
214
|
+
|
|
215
|
+
</TabItem>
|
|
216
|
+
<TabItem value="vue" label="Vue">
|
|
217
|
+
|
|
218
|
+
```vue
|
|
219
|
+
<script setup lang="ts">
|
|
220
|
+
|
|
221
|
+
interface Employee {
|
|
222
|
+
id: number;
|
|
223
|
+
name: string;
|
|
224
|
+
department: string;
|
|
225
|
+
salary: number;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const data: Employee[] = [
|
|
229
|
+
{ id: 1, name: 'Alice Johnson', department: 'Engineering', salary: 95000 },
|
|
230
|
+
{ id: 2, name: 'Bob Smith', department: 'Marketing', salary: 72000 },
|
|
231
|
+
{ id: 3, name: 'Carol Williams', department: 'Engineering', salary: 110000 },
|
|
232
|
+
{ id: 4, name: 'David Brown', department: 'Sales', salary: 68000 },
|
|
233
|
+
{ id: 5, name: 'Eva Martinez', department: 'Marketing', salary: 78000 },
|
|
234
|
+
];
|
|
235
|
+
|
|
236
|
+
const columns: IColumnDef<Employee>[] = [
|
|
237
|
+
{ columnId: 'name', name: 'Name', sortable: true },
|
|
238
|
+
{
|
|
239
|
+
columnId: 'department', name: 'Department', sortable: true,
|
|
240
|
+
filterable: { type: 'multiSelect', options: ['Engineering', 'Marketing', 'Sales'] },
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
columnId: 'salary', name: 'Salary', type: 'numeric', sortable: true, editable: true,
|
|
244
|
+
valueFormatter: (value) =>
|
|
245
|
+
new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(value as number),
|
|
246
|
+
},
|
|
247
|
+
];
|
|
248
|
+
|
|
249
|
+
const gridProps = {
|
|
250
|
+
columns,
|
|
251
|
+
data,
|
|
252
|
+
getRowId: (row: Employee) => row.id,
|
|
253
|
+
defaultPageSize: 10,
|
|
254
|
+
defaultSortBy: 'name',
|
|
255
|
+
statusBar: true,
|
|
256
|
+
};
|
|
257
|
+
</script>
|
|
258
|
+
|
|
259
|
+
<template>
|
|
260
|
+
<OGrid :gridProps="gridProps" />
|
|
261
|
+
</template>
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
:::tip Switching UI libraries
|
|
265
|
+
Same component API across Vue packages. To switch, just change the import:
|
|
266
|
+
|
|
267
|
+
- **Radix (Headless UI)** (lightweight): `from '@alaarab/ogrid-vue-radix'`
|
|
268
|
+
- **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'` — wrap in `<v-app>` for theming
|
|
269
|
+
- **PrimeVue**: `from '@alaarab/ogrid-vue-primevue'`
|
|
270
|
+
:::
|
|
271
|
+
|
|
272
|
+
</TabItem>
|
|
273
|
+
<TabItem value="js" label="Vanilla JS">
|
|
274
|
+
|
|
275
|
+
```js
|
|
276
|
+
|
|
277
|
+
const grid = new OGrid(document.getElementById('grid'), {
|
|
278
|
+
columns: [
|
|
279
|
+
{ columnId: 'name', name: 'Name', sortable: true },
|
|
280
|
+
{
|
|
281
|
+
columnId: 'department',
|
|
282
|
+
name: 'Department',
|
|
283
|
+
sortable: true,
|
|
284
|
+
filterable: { type: 'multiSelect', options: ['Engineering', 'Marketing', 'Sales'] },
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
columnId: 'salary',
|
|
288
|
+
name: 'Salary',
|
|
289
|
+
type: 'numeric',
|
|
290
|
+
sortable: true,
|
|
291
|
+
editable: true,
|
|
292
|
+
valueFormatter: (value) =>
|
|
293
|
+
new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(value),
|
|
294
|
+
},
|
|
295
|
+
],
|
|
296
|
+
data: [
|
|
297
|
+
{ id: 1, name: 'Alice Johnson', department: 'Engineering', salary: 95000 },
|
|
298
|
+
{ id: 2, name: 'Bob Smith', department: 'Marketing', salary: 72000 },
|
|
299
|
+
{ id: 3, name: 'Carol Williams', department: 'Engineering', salary: 110000 },
|
|
300
|
+
{ id: 4, name: 'David Brown', department: 'Sales', salary: 68000 },
|
|
301
|
+
{ id: 5, name: 'Eva Martinez', department: 'Marketing', salary: 78000 },
|
|
302
|
+
],
|
|
303
|
+
getRowId: (row) => row.id,
|
|
304
|
+
pageSize: 10,
|
|
305
|
+
editable: true,
|
|
306
|
+
});
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
:::tip
|
|
310
|
+
The JS package uses a class-based imperative API. See the [Vanilla JS guide](./vanilla-js) for the full API including events, grid methods, and theming.
|
|
311
|
+
:::
|
|
312
|
+
|
|
313
|
+
</TabItem>
|
|
314
|
+
</Tabs>
|
|
315
|
+
|
|
316
|
+
## What You Get
|
|
317
|
+
|
|
318
|
+
With just this code:
|
|
319
|
+
|
|
320
|
+
- **Sorting** -- click column headers to sort ascending/descending
|
|
321
|
+
- **Filtering** -- click the filter icon on Department to filter by value
|
|
322
|
+
- **Inline editing** -- double-click any salary cell to edit
|
|
323
|
+
- **Numeric formatting** -- `type: 'numeric'` right-aligns; `valueFormatter` displays currency
|
|
324
|
+
- **Pagination, keyboard nav, cell selection, status bar** -- all built in
|
|
325
|
+
|
|
326
|
+
## Key Concepts
|
|
327
|
+
|
|
328
|
+
| Concept | Description |
|
|
329
|
+
|---------|-------------|
|
|
330
|
+
| `IColumnDef<T>` | Column config. `columnId` matches a key on `T` (or use `valueGetter`). |
|
|
331
|
+
| `getRowId` | Returns a unique `string \| number` per row for selection, editing, and re-rendering. |
|
|
332
|
+
| `layoutMode` | `'fill'` (default) fills container; `'content'` sizes to content. |
|
|
333
|
+
|
|
334
|
+
## Using the Grid API
|
|
335
|
+
|
|
336
|
+
<Tabs groupId="framework">
|
|
337
|
+
<TabItem value="react" label="React" default>
|
|
338
|
+
|
|
339
|
+
```tsx
|
|
340
|
+
|
|
341
|
+
function App() {
|
|
342
|
+
const gridRef = useRef<IOGridApi<Employee>>(null);
|
|
343
|
+
|
|
344
|
+
return (
|
|
345
|
+
<>
|
|
346
|
+
<button onClick={() => console.log(gridRef.current?.getColumnState())}>
|
|
347
|
+
Log State
|
|
348
|
+
</button>
|
|
349
|
+
<OGrid<Employee> ref={gridRef} columns={columns} data={data} getRowId={(row) => row.id} />
|
|
350
|
+
</>
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
</TabItem>
|
|
356
|
+
<TabItem value="angular" label="Angular">
|
|
357
|
+
|
|
358
|
+
```typescript
|
|
359
|
+
|
|
360
|
+
@Component({
|
|
361
|
+
standalone: true,
|
|
362
|
+
imports: [OGridComponent],
|
|
363
|
+
template: `
|
|
364
|
+
<button (click)="logState()">Log State</button>
|
|
365
|
+
<ogrid [props]="gridProps" />
|
|
366
|
+
`
|
|
367
|
+
})
|
|
368
|
+
export class AppComponent {
|
|
369
|
+
constructor(private gridService: OGridService) {}
|
|
370
|
+
|
|
371
|
+
logState() {
|
|
372
|
+
console.log(this.gridService.getColumnState());
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
gridProps = { columns, data, getRowId: (row: any) => row.id };
|
|
376
|
+
}
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
</TabItem>
|
|
380
|
+
<TabItem value="vue" label="Vue">
|
|
381
|
+
|
|
382
|
+
```vue
|
|
383
|
+
<script setup lang="ts">
|
|
384
|
+
|
|
385
|
+
const { getColumnState } = useOGrid({ columns, data, getRowId: (row) => row.id });
|
|
386
|
+
|
|
387
|
+
function logState() {
|
|
388
|
+
console.log(getColumnState());
|
|
389
|
+
}
|
|
390
|
+
</script>
|
|
391
|
+
|
|
392
|
+
<template>
|
|
393
|
+
<button @click="logState">Log State</button>
|
|
394
|
+
<OGrid :gridProps="{ columns, data, getRowId: (row) => row.id }" />
|
|
395
|
+
</template>
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
</TabItem>
|
|
399
|
+
<TabItem value="js" label="Vanilla JS">
|
|
400
|
+
|
|
401
|
+
```js
|
|
402
|
+
|
|
403
|
+
const grid = new OGrid(document.getElementById('grid'), {
|
|
404
|
+
columns, data, getRowId: (row) => row.id,
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
// Programmatic control
|
|
408
|
+
const api = grid.getApi();
|
|
409
|
+
console.log(api.getColumnState());
|
|
410
|
+
api.setRowData(newData);
|
|
411
|
+
|
|
412
|
+
// Cleanup
|
|
413
|
+
grid.destroy();
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
</TabItem>
|
|
417
|
+
</Tabs>
|
|
418
|
+
|
|
419
|
+
## Next Steps
|
|
420
|
+
|
|
421
|
+
- [Sorting](../features/sorting), [Filtering](../features/filtering), [Editing](../features/editing) -- core features
|
|
422
|
+
- [Grid API](../api/grid-api) -- imperative methods
|
|
423
|
+
- [Column Definitions](../api/column-def) -- all column options
|
|
424
|
+
- [Controlled vs Uncontrolled](../guides/controlled-vs-uncontrolled) -- managing state externally
|
|
425
|
+
- [Server-Side Data](../features/server-side-data) -- connect to REST APIs or GraphQL
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 4
|
|
3
|
+
title: Vanilla JS
|
|
4
|
+
description: Use OGrid without React — pure JavaScript, class-based API
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# Vanilla JS Quick Start
|
|
9
|
+
|
|
10
|
+
OGrid's vanilla JS package provides the same features as the React packages with a class-based, imperative API. No React, no virtual DOM — just a container element and an options object.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install @alaarab/ogrid-js
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Basic Example
|
|
19
|
+
|
|
20
|
+
```html
|
|
21
|
+
<div id="grid" style="height: 400px;"></div>
|
|
22
|
+
|
|
23
|
+
<script type="module">
|
|
24
|
+
import { OGrid } from '@alaarab/ogrid-js';
|
|
25
|
+
import '@alaarab/ogrid-js/styles'; // default theme (light + dark mode)
|
|
26
|
+
|
|
27
|
+
const grid = new OGrid(document.getElementById('grid'), {
|
|
28
|
+
columns: [
|
|
29
|
+
{ columnId: 'name', name: 'Name', sortable: true },
|
|
30
|
+
{ columnId: 'department', name: 'Department', sortable: true },
|
|
31
|
+
{
|
|
32
|
+
columnId: 'salary',
|
|
33
|
+
name: 'Salary',
|
|
34
|
+
type: 'numeric',
|
|
35
|
+
sortable: true,
|
|
36
|
+
editable: true,
|
|
37
|
+
valueFormatter: (v) => `$${Number(v).toLocaleString()}`,
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
data: [
|
|
41
|
+
{ id: 1, name: 'Alice Johnson', department: 'Engineering', salary: 95000 },
|
|
42
|
+
{ id: 2, name: 'Bob Smith', department: 'Marketing', salary: 72000 },
|
|
43
|
+
{ id: 3, name: 'Carol Williams', department: 'Sales', salary: 110000 },
|
|
44
|
+
{ id: 4, name: 'David Brown', department: 'Engineering', salary: 68000 },
|
|
45
|
+
{ id: 5, name: 'Eva Martinez', department: 'Marketing', salary: 78000 },
|
|
46
|
+
],
|
|
47
|
+
getRowId: (row) => row.id,
|
|
48
|
+
pageSize: 10,
|
|
49
|
+
editable: true,
|
|
50
|
+
cellSelection: true,
|
|
51
|
+
statusBar: true,
|
|
52
|
+
});
|
|
53
|
+
</script>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Live Demo
|
|
57
|
+
|
|
58
|
+
<VanillaJSDemo />
|
|
59
|
+
|
|
60
|
+
## What You Get
|
|
61
|
+
|
|
62
|
+
With this code you have:
|
|
63
|
+
|
|
64
|
+
- **Sorting** — click column headers
|
|
65
|
+
- **Inline editing** — double-click any salary cell
|
|
66
|
+
- **Cell selection** — click and drag to select ranges
|
|
67
|
+
- **Keyboard navigation** — arrow keys, Tab, Home/End, Ctrl+Arrow
|
|
68
|
+
- **Clipboard** — Ctrl+C/V/X
|
|
69
|
+
- **Undo/redo** — Ctrl+Z/Y
|
|
70
|
+
- **Status bar** — row count and selection aggregations
|
|
71
|
+
- **Pagination** — page controls at the bottom
|
|
72
|
+
|
|
73
|
+
## Constructor
|
|
74
|
+
|
|
75
|
+
```js
|
|
76
|
+
const grid = new OGrid(containerElement, options);
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
| Parameter | Type | Description |
|
|
80
|
+
|-----------|------|-------------|
|
|
81
|
+
| `container` | `HTMLElement` | The DOM element to render into. OGrid fills this element. |
|
|
82
|
+
| `options` | `OGridOptions<T>` | Grid configuration (see below). |
|
|
83
|
+
|
|
84
|
+
## Key Options
|
|
85
|
+
|
|
86
|
+
| Option | Type | Default | Description |
|
|
87
|
+
|--------|------|---------|-------------|
|
|
88
|
+
| `columns` | `IColumnDef<T>[]` | **required** | Column definitions |
|
|
89
|
+
| `data` | `T[]` | — | Client-side data array |
|
|
90
|
+
| `dataSource` | `IDataSource<T>` | — | Server-side data source (mutually exclusive with `data`) |
|
|
91
|
+
| `getRowId` | `(item: T) => RowId` | **required** | Unique row identifier |
|
|
92
|
+
| `pageSize` | `number` | `20` | Rows per page |
|
|
93
|
+
| `sort` | `{ field, direction }` | — | Initial sort |
|
|
94
|
+
| `filters` | `IFilters` | — | Initial filters |
|
|
95
|
+
| `editable` | `boolean` | `false` | Enable cell editing |
|
|
96
|
+
| `cellSelection` | `boolean` | `false` | Enable spreadsheet-style selection |
|
|
97
|
+
| `rowSelection` | `'single' \| 'multiple'` | — | Row selection mode |
|
|
98
|
+
| `sideBar` | `boolean \| ISideBarDef` | — | Show sidebar (columns + filters panels) |
|
|
99
|
+
| `layoutMode` | `'fill' \| 'content'` | `'fill'` | `'fill'` stretches to container; `'content'` sizes to data |
|
|
100
|
+
| `pinnedColumns` | `Record<string, 'left' \| 'right'>` | — | Pin columns to edges |
|
|
101
|
+
|
|
102
|
+
## Events
|
|
103
|
+
|
|
104
|
+
Listen for events with `.on()`:
|
|
105
|
+
|
|
106
|
+
```js
|
|
107
|
+
grid.on('cellValueChanged', (event) => {
|
|
108
|
+
console.log(`Cell ${event.columnId} changed from ${event.oldValue} to ${event.newValue}`);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
grid.on('sortChange', ({ field, direction }) => {
|
|
112
|
+
console.log(`Sorted by ${field} ${direction}`);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
grid.on('selectionChange', ({ selectedRows }) => {
|
|
116
|
+
console.log(`${selectedRows.length} rows selected`);
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
| Event | Payload | Fired when |
|
|
121
|
+
|-------|---------|------------|
|
|
122
|
+
| `cellValueChanged` | `{ item, columnId, oldValue, newValue }` | A cell edit is committed |
|
|
123
|
+
| `sortChange` | `{ field, direction }` | Sort changes |
|
|
124
|
+
| `filterChange` | `{ filters }` | Filters change |
|
|
125
|
+
| `pageChange` | `{ page }` | Page changes |
|
|
126
|
+
| `selectionChange` | `{ selectedRows, selectedRowIds }` | Row selection changes |
|
|
127
|
+
|
|
128
|
+
## Grid API
|
|
129
|
+
|
|
130
|
+
Access the imperative API via `grid.api`:
|
|
131
|
+
|
|
132
|
+
```js
|
|
133
|
+
// Update data
|
|
134
|
+
grid.api.setRowData(newData);
|
|
135
|
+
|
|
136
|
+
// Get current state
|
|
137
|
+
const state = grid.api.getColumnState();
|
|
138
|
+
|
|
139
|
+
// Export to CSV
|
|
140
|
+
grid.api.exportToCsv('my-data.csv');
|
|
141
|
+
|
|
142
|
+
// Programmatic sort
|
|
143
|
+
grid.api.setSort('salary', 'desc');
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
See the full [JS API Reference](../api/js-api) for all methods.
|
|
147
|
+
|
|
148
|
+
## Theming
|
|
149
|
+
|
|
150
|
+
The default theme uses CSS custom properties. Override them to match your design:
|
|
151
|
+
|
|
152
|
+
```css
|
|
153
|
+
:root {
|
|
154
|
+
--ogrid-primary: #0066cc; /* buttons, active page */
|
|
155
|
+
--ogrid-selection: #0078d4; /* active cell outline */
|
|
156
|
+
--ogrid-bg: #ffffff; /* background */
|
|
157
|
+
--ogrid-fg: #242424; /* text color */
|
|
158
|
+
--ogrid-border: #e0e0e0; /* borders */
|
|
159
|
+
--ogrid-bg-subtle: #f3f2f1; /* header background */
|
|
160
|
+
--ogrid-bg-hover: #f5f5f5; /* row hover */
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
For dark mode, set `data-theme="dark"` on a parent element or rely on `prefers-color-scheme`:
|
|
165
|
+
|
|
166
|
+
```css
|
|
167
|
+
[data-theme='dark'] {
|
|
168
|
+
--ogrid-bg: #1a1a24;
|
|
169
|
+
--ogrid-fg: #e0e0e0;
|
|
170
|
+
--ogrid-border: #333340;
|
|
171
|
+
/* ... */
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Or skip the default theme entirely and write your own CSS targeting the `ogrid-*` class names.
|
|
176
|
+
|
|
177
|
+
## Cleanup
|
|
178
|
+
|
|
179
|
+
Always destroy the grid when you're done:
|
|
180
|
+
|
|
181
|
+
```js
|
|
182
|
+
grid.destroy();
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
This removes all DOM elements, event listeners, and ResizeObservers.
|
|
186
|
+
|
|
187
|
+
## Next Steps
|
|
188
|
+
|
|
189
|
+
- [JS API Reference](../api/js-api) — full method and options reference
|
|
190
|
+
- [Features](../features/sorting) — all grid features work identically in JS
|
|
191
|
+
- [Theming Guide](../guides/theming) — deep dive into CSS customization
|