@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,241 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 1
|
|
3
|
+
title: Sorting
|
|
4
|
+
description: Enable column sorting with click-to-toggle, custom comparators, and server-side support.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# Sorting
|
|
9
|
+
|
|
10
|
+
Add sortable columns to your grid with a single prop. Users click a column header to cycle through ascending, descending, and unsorted states. A sort indicator arrow shows the current direction.
|
|
11
|
+
|
|
12
|
+
## Live Demo
|
|
13
|
+
|
|
14
|
+
<SortingDemo />
|
|
15
|
+
|
|
16
|
+
:::tip Try it in your framework
|
|
17
|
+
The demo above uses Radix UI for styling. To see this feature with your framework's design system (Fluent UI, Material UI, Vuetify, PrimeNG, etc.), click **"Open in online demo"** below the demo.
|
|
18
|
+
:::
|
|
19
|
+
|
|
20
|
+
## Quick Example
|
|
21
|
+
|
|
22
|
+
<Tabs groupId="framework">
|
|
23
|
+
<TabItem value="react" label="React" default>
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
|
|
27
|
+
const columns = [
|
|
28
|
+
{ columnId: 'name', name: 'Name', sortable: true },
|
|
29
|
+
{ columnId: 'age', name: 'Age', sortable: true, type: 'numeric' as const },
|
|
30
|
+
{ columnId: 'department', name: 'Department', sortable: true },
|
|
31
|
+
{
|
|
32
|
+
columnId: 'salary',
|
|
33
|
+
name: 'Salary',
|
|
34
|
+
sortable: true,
|
|
35
|
+
type: 'numeric' as const,
|
|
36
|
+
valueFormatter: (v) => `$${Number(v).toLocaleString()}`,
|
|
37
|
+
},
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
function App() {
|
|
41
|
+
return (
|
|
42
|
+
<OGrid
|
|
43
|
+
columns={columns}
|
|
44
|
+
data={people}
|
|
45
|
+
getRowId={(item) => item.id}
|
|
46
|
+
defaultPageSize={10}
|
|
47
|
+
/>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
:::tip Switching UI libraries
|
|
53
|
+
The `OGrid` component has the same props across all React UI packages. To switch, just change the import:
|
|
54
|
+
|
|
55
|
+
- **Radix** (lightweight, default): `from '@alaarab/ogrid-react-radix'`
|
|
56
|
+
- **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'` — wrap in `<FluentProvider>`
|
|
57
|
+
- **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'` — wrap in `<ThemeProvider>`
|
|
58
|
+
:::
|
|
59
|
+
|
|
60
|
+
</TabItem>
|
|
61
|
+
<TabItem value="angular" label="Angular">
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
|
|
65
|
+
@Component({
|
|
66
|
+
standalone: true,
|
|
67
|
+
imports: [OGridComponent],
|
|
68
|
+
template: `<ogrid [props]="gridProps" />`
|
|
69
|
+
})
|
|
70
|
+
export class GridComponent {
|
|
71
|
+
gridProps = {
|
|
72
|
+
columns: [
|
|
73
|
+
{ columnId: 'name', name: 'Name', sortable: true },
|
|
74
|
+
{ columnId: 'age', name: 'Age', sortable: true, type: 'numeric' },
|
|
75
|
+
{ columnId: 'department', name: 'Department', sortable: true },
|
|
76
|
+
{
|
|
77
|
+
columnId: 'salary',
|
|
78
|
+
name: 'Salary',
|
|
79
|
+
sortable: true,
|
|
80
|
+
type: 'numeric',
|
|
81
|
+
valueFormatter: (v: unknown) => `$${Number(v).toLocaleString()}`,
|
|
82
|
+
},
|
|
83
|
+
] as IColumnDef<Person>[],
|
|
84
|
+
data: people,
|
|
85
|
+
getRowId: (item: Person) => item.id,
|
|
86
|
+
defaultPageSize: 10,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
:::tip Switching UI libraries
|
|
92
|
+
Same component API across Angular packages. To switch, just change the import:
|
|
93
|
+
|
|
94
|
+
- **Radix (CDK)**: `from '@alaarab/ogrid-angular-radix'` *(default, lightweight)*
|
|
95
|
+
- **Angular Material**: `from '@alaarab/ogrid-angular-material'`
|
|
96
|
+
- **PrimeNG**: `from '@alaarab/ogrid-angular-primeng'`
|
|
97
|
+
|
|
98
|
+
All components are standalone — no NgModule required.
|
|
99
|
+
:::
|
|
100
|
+
|
|
101
|
+
</TabItem>
|
|
102
|
+
<TabItem value="vue" label="Vue">
|
|
103
|
+
|
|
104
|
+
```vue
|
|
105
|
+
<script setup lang="ts">
|
|
106
|
+
|
|
107
|
+
const columns: IColumnDef<Person>[] = [
|
|
108
|
+
{ columnId: 'name', name: 'Name', sortable: true },
|
|
109
|
+
{ columnId: 'age', name: 'Age', sortable: true, type: 'numeric' },
|
|
110
|
+
{ columnId: 'department', name: 'Department', sortable: true },
|
|
111
|
+
{
|
|
112
|
+
columnId: 'salary',
|
|
113
|
+
name: 'Salary',
|
|
114
|
+
sortable: true,
|
|
115
|
+
type: 'numeric',
|
|
116
|
+
valueFormatter: (v) => `$${Number(v).toLocaleString()}`,
|
|
117
|
+
},
|
|
118
|
+
];
|
|
119
|
+
|
|
120
|
+
const gridProps = {
|
|
121
|
+
columns,
|
|
122
|
+
data: people,
|
|
123
|
+
getRowId: (item) => item.id,
|
|
124
|
+
defaultPageSize: 10,
|
|
125
|
+
};
|
|
126
|
+
</script>
|
|
127
|
+
|
|
128
|
+
<template>
|
|
129
|
+
<OGrid :gridProps="gridProps" />
|
|
130
|
+
</template>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
:::tip Switching UI libraries
|
|
134
|
+
Same component API across Vue packages. To switch, just change the import:
|
|
135
|
+
|
|
136
|
+
- **Radix (Headless UI)**: `from '@alaarab/ogrid-vue-radix'` *(default, lightweight)*
|
|
137
|
+
- **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'` — wrap in `<v-app>` for theming
|
|
138
|
+
- **PrimeVue**: `from '@alaarab/ogrid-vue-primevue'`
|
|
139
|
+
:::
|
|
140
|
+
|
|
141
|
+
</TabItem>
|
|
142
|
+
<TabItem value="js" label="Vanilla JS">
|
|
143
|
+
|
|
144
|
+
```js
|
|
145
|
+
|
|
146
|
+
const grid = new OGrid(document.getElementById('grid'), {
|
|
147
|
+
columns: [
|
|
148
|
+
{ columnId: 'name', name: 'Name', sortable: true },
|
|
149
|
+
{ columnId: 'age', name: 'Age', sortable: true, type: 'numeric' },
|
|
150
|
+
{ columnId: 'department', name: 'Department', sortable: true },
|
|
151
|
+
{
|
|
152
|
+
columnId: 'salary',
|
|
153
|
+
name: 'Salary',
|
|
154
|
+
sortable: true,
|
|
155
|
+
type: 'numeric',
|
|
156
|
+
valueFormatter: (v) => `$${Number(v).toLocaleString()}`,
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
data: people,
|
|
160
|
+
getRowId: (item) => item.id,
|
|
161
|
+
pageSize: 10,
|
|
162
|
+
});
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
</TabItem>
|
|
166
|
+
</Tabs>
|
|
167
|
+
|
|
168
|
+
## How It Works
|
|
169
|
+
|
|
170
|
+
Set `sortable: true` on any column definition to make it sortable. When a user clicks the column header, OGrid toggles the sort direction: unsorted, ascending, then descending.
|
|
171
|
+
|
|
172
|
+
OGrid supports both **uncontrolled** and **controlled** sorting:
|
|
173
|
+
|
|
174
|
+
- **Uncontrolled** -- the grid manages sort state internally. Use `defaultSortBy` and `defaultSortDirection` to set the initial sort.
|
|
175
|
+
- **Controlled** -- you own the state. Pass `sort` and `onSortChange` to the grid.
|
|
176
|
+
|
|
177
|
+
### Custom Comparator
|
|
178
|
+
|
|
179
|
+
For columns that need custom sort logic (e.g., sorting by a nested field or special ordering), provide a `compare` function on the column definition:
|
|
180
|
+
|
|
181
|
+
```tsx
|
|
182
|
+
const columns = [
|
|
183
|
+
{
|
|
184
|
+
columnId: 'priority',
|
|
185
|
+
name: 'Priority',
|
|
186
|
+
sortable: true,
|
|
187
|
+
compare: (a, b) => {
|
|
188
|
+
const order = { High: 0, Medium: 1, Low: 2 };
|
|
189
|
+
return order[a.priority] - order[b.priority];
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
];
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Server-Side Sorting
|
|
196
|
+
|
|
197
|
+
When using a `dataSource`, the sort parameter is forwarded to `fetchPage()`. The grid does not sort the data itself -- your server handles it:
|
|
198
|
+
|
|
199
|
+
```tsx
|
|
200
|
+
const dataSource: IDataSource<Project> = {
|
|
201
|
+
fetchPage: async ({ sort, page, pageSize, filters }) => {
|
|
202
|
+
const res = await fetch(`/api/projects?sort=${sort?.field}&dir=${sort?.direction}&page=${page}`);
|
|
203
|
+
const json = await res.json();
|
|
204
|
+
return { items: json.data, totalCount: json.total };
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Controlled Example
|
|
210
|
+
|
|
211
|
+
```tsx
|
|
212
|
+
function App() {
|
|
213
|
+
const [sort, setSort] = useState({ field: 'name', direction: 'asc' as const });
|
|
214
|
+
|
|
215
|
+
return (
|
|
216
|
+
<OGrid
|
|
217
|
+
columns={columns}
|
|
218
|
+
data={people}
|
|
219
|
+
getRowId={(item) => item.id}
|
|
220
|
+
sort={sort}
|
|
221
|
+
onSortChange={setSort}
|
|
222
|
+
/>
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Props
|
|
228
|
+
|
|
229
|
+
| Prop | Type | Default | Description |
|
|
230
|
+
|------|------|---------|-------------|
|
|
231
|
+
| `sortable` | `boolean` | `false` | Set on `IColumnDef` to enable sorting for that column. |
|
|
232
|
+
| `compare` | `(a: T, b: T) => number` | -- | Custom sort comparator on `IColumnDef`. |
|
|
233
|
+
| `sort` | `{ field: string; direction: 'asc' \| 'desc' }` | -- | Controlled sort state on `OGrid`. |
|
|
234
|
+
| `onSortChange` | `(sort: { field: string; direction: 'asc' \| 'desc' }) => void` | -- | Called when sort changes (controlled mode). |
|
|
235
|
+
| `defaultSortBy` | `string` | -- | Initial sort column (uncontrolled mode). |
|
|
236
|
+
| `defaultSortDirection` | `'asc' \| 'desc'` | `'asc'` | Initial sort direction (uncontrolled mode). |
|
|
237
|
+
|
|
238
|
+
## Related
|
|
239
|
+
|
|
240
|
+
- [Filtering](./filtering) -- filter rows by column values
|
|
241
|
+
- [Pagination](./pagination) -- paginate sorted results
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 5
|
|
3
|
+
title: Spreadsheet Selection
|
|
4
|
+
description: Excel-like cell selection with active cell, range selection, and drag-to-select.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# Spreadsheet Selection
|
|
9
|
+
|
|
10
|
+
OGrid provides Excel-like cell selection out of the box. Click a cell to make it active, drag or Shift+click to select a range. The active cell gets a green border, and selected ranges are highlighted with a green background.
|
|
11
|
+
|
|
12
|
+
## Live Demo
|
|
13
|
+
|
|
14
|
+
<SpreadsheetSelectionDemo />
|
|
15
|
+
|
|
16
|
+
:::tip Framework-Specific Styling
|
|
17
|
+
The live demo above shows **React Radix UI** styling (lightweight default). To see how this feature looks in your framework's design system, click the framework buttons above the demo to open online demo:
|
|
18
|
+
- **React** — Radix UI styling
|
|
19
|
+
- **Angular** — Angular Material styling
|
|
20
|
+
- **Vue** — Vuetify styling
|
|
21
|
+
- **JS** — Vanilla JS default theme
|
|
22
|
+
|
|
23
|
+
Each framework renders OGrid with its native components, so the look and feel matches your design system.
|
|
24
|
+
:::
|
|
25
|
+
|
|
26
|
+
## Quick Example
|
|
27
|
+
|
|
28
|
+
<Tabs groupId="framework">
|
|
29
|
+
<TabItem value="react" label="React" default>
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
|
|
33
|
+
function App() {
|
|
34
|
+
return (
|
|
35
|
+
<OGrid
|
|
36
|
+
columns={columns}
|
|
37
|
+
data={items}
|
|
38
|
+
getRowId={(item) => item.id}
|
|
39
|
+
cellSelection // default: true
|
|
40
|
+
/>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
:::tip Switching UI libraries
|
|
46
|
+
The `OGrid` component has the same props across all React UI packages. To switch, just change the import:
|
|
47
|
+
|
|
48
|
+
- **Radix** (lightweight, default): `from '@alaarab/ogrid-react-radix'`
|
|
49
|
+
- **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'` — wrap in `<FluentProvider>`
|
|
50
|
+
- **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'` — wrap in `<ThemeProvider>`
|
|
51
|
+
:::
|
|
52
|
+
|
|
53
|
+
</TabItem>
|
|
54
|
+
<TabItem value="angular" label="Angular">
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
|
|
58
|
+
@Component({
|
|
59
|
+
standalone: true,
|
|
60
|
+
imports: [OGridComponent],
|
|
61
|
+
template: `<ogrid [props]="gridProps" />`
|
|
62
|
+
})
|
|
63
|
+
export class GridComponent {
|
|
64
|
+
gridProps = {
|
|
65
|
+
columns,
|
|
66
|
+
data: items,
|
|
67
|
+
getRowId: (item: any) => item.id,
|
|
68
|
+
cellSelection: true,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
:::tip Switching UI libraries
|
|
74
|
+
Same component API across Angular packages. To switch, just change the import:
|
|
75
|
+
|
|
76
|
+
- **Radix (CDK)**: `from '@alaarab/ogrid-angular-radix'` *(default, lightweight)*
|
|
77
|
+
- **Angular Material**: `from '@alaarab/ogrid-angular-material'`
|
|
78
|
+
- **PrimeNG**: `from '@alaarab/ogrid-angular-primeng'`
|
|
79
|
+
|
|
80
|
+
All components are standalone — no NgModule required.
|
|
81
|
+
:::
|
|
82
|
+
|
|
83
|
+
</TabItem>
|
|
84
|
+
<TabItem value="vue" label="Vue">
|
|
85
|
+
|
|
86
|
+
```vue
|
|
87
|
+
<script setup lang="ts">
|
|
88
|
+
|
|
89
|
+
const gridProps = {
|
|
90
|
+
columns,
|
|
91
|
+
data: items,
|
|
92
|
+
getRowId: (item) => item.id,
|
|
93
|
+
cellSelection: true,
|
|
94
|
+
};
|
|
95
|
+
</script>
|
|
96
|
+
|
|
97
|
+
<template>
|
|
98
|
+
<OGrid :gridProps="gridProps" />
|
|
99
|
+
</template>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
:::tip Switching UI libraries
|
|
103
|
+
Same component API across Vue packages. To switch, just change the import:
|
|
104
|
+
|
|
105
|
+
- **Radix (Headless UI)**: `from '@alaarab/ogrid-vue-radix'` *(default, lightweight)*
|
|
106
|
+
- **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'` — wrap in `<v-app>` for theming
|
|
107
|
+
- **PrimeVue**: `from '@alaarab/ogrid-vue-primevue'`
|
|
108
|
+
:::
|
|
109
|
+
|
|
110
|
+
</TabItem>
|
|
111
|
+
<TabItem value="js" label="Vanilla JS">
|
|
112
|
+
|
|
113
|
+
```js
|
|
114
|
+
|
|
115
|
+
const grid = new OGrid(document.getElementById('grid'), {
|
|
116
|
+
columns: columns,
|
|
117
|
+
data: items,
|
|
118
|
+
getRowId: (item) => item.id,
|
|
119
|
+
cellSelection: true,
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
</TabItem>
|
|
124
|
+
</Tabs>
|
|
125
|
+
|
|
126
|
+
## How It Works
|
|
127
|
+
|
|
128
|
+
Cell selection is **enabled by default** (`cellSelection={true}`). When active:
|
|
129
|
+
|
|
130
|
+
- **Click** a cell to make it the active cell (green border).
|
|
131
|
+
- **Shift+Click** another cell to select a rectangular range from the active cell to the clicked cell.
|
|
132
|
+
- **Click and drag** across cells to select a range.
|
|
133
|
+
- **Ctrl+A** selects all cells in the grid.
|
|
134
|
+
- **Arrow keys** move the active cell. **Shift+Arrow** extends the selection range.
|
|
135
|
+
|
|
136
|
+
:::info Cell Selection vs Row Selection
|
|
137
|
+
**Cell selection** (this page) selects individual cells using click/drag. The **Ctrl+A** keyboard shortcut selects all **cells** in the grid for copy/paste/fill operations.
|
|
138
|
+
|
|
139
|
+
This is separate from **row selection** ([Row Selection](./row-selection)), which selects entire rows using checkboxes. Row selection's header checkbox selects all **rows** at once.
|
|
140
|
+
|
|
141
|
+
You can use both features together -- cell selection and row selection are independent.
|
|
142
|
+
:::
|
|
143
|
+
|
|
144
|
+
The selection range is represented by `ISelectionRange`:
|
|
145
|
+
|
|
146
|
+
```tsx
|
|
147
|
+
interface ISelectionRange {
|
|
148
|
+
startRow: number; // row index of the anchor cell
|
|
149
|
+
startCol: number; // column index of the anchor cell
|
|
150
|
+
endRow: number; // row index of the end cell
|
|
151
|
+
endCol: number; // column index of the end cell
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Performance
|
|
156
|
+
|
|
157
|
+
Drag selection is optimized with `requestAnimationFrame` and DOM attribute toggling. During a drag, React state is not updated on every mouse move -- only on mouse up. This keeps the grid responsive even with thousands of cells.
|
|
158
|
+
|
|
159
|
+
### Disabling Cell Selection
|
|
160
|
+
|
|
161
|
+
Pass `cellSelection={false}` to disable all spreadsheet-style selection. This also disables the fill handle, clipboard integration, and context menu cell operations:
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
<OGrid
|
|
165
|
+
columns={columns}
|
|
166
|
+
data={items}
|
|
167
|
+
getRowId={(item) => item.id}
|
|
168
|
+
cellSelection={false}
|
|
169
|
+
/>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Selection Styling
|
|
173
|
+
|
|
174
|
+
Selection colors use CSS custom properties for easy theming:
|
|
175
|
+
|
|
176
|
+
```css
|
|
177
|
+
--ogrid-selection: #217346; /* Excel green, used for active cell border */
|
|
178
|
+
--ogrid-selection-bg: rgba(33, 115, 70, 0.08); /* range background */
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Props
|
|
182
|
+
|
|
183
|
+
| Prop | Type | Default | Description |
|
|
184
|
+
|------|------|---------|-------------|
|
|
185
|
+
| `cellSelection` | `boolean` | `true` | Enable or disable spreadsheet-style cell selection. |
|
|
186
|
+
|
|
187
|
+
## Keyboard Shortcuts
|
|
188
|
+
|
|
189
|
+
| Key | Action |
|
|
190
|
+
|-----|--------|
|
|
191
|
+
| Click | Select a single cell |
|
|
192
|
+
| Shift+Click | Extend selection to a range |
|
|
193
|
+
| Click+Drag | Select a range by dragging |
|
|
194
|
+
| Arrow keys | Move active cell |
|
|
195
|
+
| Shift+Arrow | Extend selection range |
|
|
196
|
+
| Ctrl+A | Select all cells (for copy/paste/fill operations) |
|
|
197
|
+
|
|
198
|
+
## Related
|
|
199
|
+
|
|
200
|
+
- [Editing & Clipboard](./editing) -- edit, copy/paste, and fill cells
|
|
201
|
+
- [Row Selection](./row-selection) -- select entire rows instead of cells
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 14
|
|
3
|
+
title: Status Bar
|
|
4
|
+
description: Row counts, selection counts, and numeric aggregations at the bottom of the grid
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# Status Bar
|
|
9
|
+
|
|
10
|
+
The status bar sits at the bottom of the grid and displays row counts, filter counts, selection counts, and numeric aggregations for selected cell ranges.
|
|
11
|
+
|
|
12
|
+
## Live Demo
|
|
13
|
+
|
|
14
|
+
<StatusBarDemo />
|
|
15
|
+
|
|
16
|
+
:::tip Try it in your framework
|
|
17
|
+
The demo above uses Radix UI for styling. To see this feature with your framework's design system (Fluent UI, Material UI, Vuetify, PrimeNG, etc.), click **"Open in online demo"** below the demo.
|
|
18
|
+
:::
|
|
19
|
+
|
|
20
|
+
## Quick Example
|
|
21
|
+
|
|
22
|
+
<Tabs groupId="framework">
|
|
23
|
+
<TabItem value="react" label="React" default>
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
|
|
27
|
+
function App() {
|
|
28
|
+
return (
|
|
29
|
+
<OGrid
|
|
30
|
+
columns={columns}
|
|
31
|
+
data={data}
|
|
32
|
+
getRowId={(r) => r.id}
|
|
33
|
+
statusBar
|
|
34
|
+
/>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
:::tip Switching UI libraries
|
|
40
|
+
The `OGrid` component has the same props across all React UI packages. To switch, just change the import:
|
|
41
|
+
|
|
42
|
+
- **Radix** (lightweight, default): `from '@alaarab/ogrid-react-radix'`
|
|
43
|
+
- **Fluent UI** (Microsoft 365 / SPFx): `from '@alaarab/ogrid-react-fluent'` — wrap in `<FluentProvider>`
|
|
44
|
+
- **Material UI** (MUI v7): `from '@alaarab/ogrid-react-material'` — wrap in `<ThemeProvider>`
|
|
45
|
+
:::
|
|
46
|
+
|
|
47
|
+
</TabItem>
|
|
48
|
+
<TabItem value="angular" label="Angular">
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
|
|
52
|
+
@Component({
|
|
53
|
+
standalone: true,
|
|
54
|
+
imports: [OGridComponent],
|
|
55
|
+
template: `<ogrid [props]="gridProps" />`
|
|
56
|
+
})
|
|
57
|
+
export class GridComponent {
|
|
58
|
+
gridProps = {
|
|
59
|
+
columns: columns,
|
|
60
|
+
data: data,
|
|
61
|
+
getRowId: (r: Row) => r.id,
|
|
62
|
+
statusBar: true,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
:::tip Switching UI libraries
|
|
68
|
+
Same component API across Angular packages. To switch, just change the import:
|
|
69
|
+
|
|
70
|
+
- **Radix (CDK)**: `from '@alaarab/ogrid-angular-radix'` *(default, lightweight)*
|
|
71
|
+
- **Angular Material**: `from '@alaarab/ogrid-angular-material'`
|
|
72
|
+
- **PrimeNG**: `from '@alaarab/ogrid-angular-primeng'`
|
|
73
|
+
|
|
74
|
+
All components are standalone — no NgModule required.
|
|
75
|
+
:::
|
|
76
|
+
|
|
77
|
+
</TabItem>
|
|
78
|
+
<TabItem value="vue" label="Vue">
|
|
79
|
+
|
|
80
|
+
```vue
|
|
81
|
+
<script setup lang="ts">
|
|
82
|
+
|
|
83
|
+
const gridProps = {
|
|
84
|
+
columns,
|
|
85
|
+
data,
|
|
86
|
+
getRowId: (r) => r.id,
|
|
87
|
+
statusBar: true,
|
|
88
|
+
};
|
|
89
|
+
</script>
|
|
90
|
+
|
|
91
|
+
<template>
|
|
92
|
+
<OGrid :gridProps="gridProps" />
|
|
93
|
+
</template>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
:::tip Switching UI libraries
|
|
97
|
+
Same component API across Vue packages. To switch, just change the import:
|
|
98
|
+
|
|
99
|
+
- **Radix (Headless UI)**: `from '@alaarab/ogrid-vue-radix'` *(default, lightweight)*
|
|
100
|
+
- **Vuetify**: `from '@alaarab/ogrid-vue-vuetify'` — wrap in `<v-app>` for theming
|
|
101
|
+
- **PrimeVue**: `from '@alaarab/ogrid-vue-primevue'`
|
|
102
|
+
:::
|
|
103
|
+
|
|
104
|
+
</TabItem>
|
|
105
|
+
<TabItem value="js" label="Vanilla JS">
|
|
106
|
+
|
|
107
|
+
```js
|
|
108
|
+
|
|
109
|
+
const grid = new OGrid(document.getElementById('grid'), {
|
|
110
|
+
columns: columns,
|
|
111
|
+
data: data,
|
|
112
|
+
getRowId: (r) => r.id,
|
|
113
|
+
statusBar: true,
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
</TabItem>
|
|
118
|
+
</Tabs>
|
|
119
|
+
|
|
120
|
+
Set `statusBar={true}` and the bar appears at the bottom showing "Rows: 150".
|
|
121
|
+
|
|
122
|
+
## How It Works
|
|
123
|
+
|
|
124
|
+
The status bar dynamically shows information based on the current grid state.
|
|
125
|
+
|
|
126
|
+
### Basic Row Count
|
|
127
|
+
|
|
128
|
+
With `statusBar={true}`, the bar always shows the total row count.
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
Rows: 150
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Filtered Count
|
|
135
|
+
|
|
136
|
+
When filters are active and reduce the displayed rows, a "Filtered" count appears alongside the total.
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
Rows: 150 | Filtered: 42
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Selected Row Count
|
|
143
|
+
|
|
144
|
+
When row selection is enabled and the user selects rows, a "Selected" count appears.
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
Rows: 150 | Selected: 5
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Cell Aggregations
|
|
151
|
+
|
|
152
|
+
When the user selects a range of cells that includes numeric values, the status bar shows aggregation values: Sum, Avg, Min, Max, and Count.
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
Rows: 150 | Cells: 12 | Sum: 4800 | Avg: 400 | Min: 150 | Max: 900 | Count: 12
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Aggregations:
|
|
159
|
+
- Only appear when 2 or more cells are selected.
|
|
160
|
+
- Only include cells with numeric values.
|
|
161
|
+
- `Avg` is rounded to 2 decimal places.
|
|
162
|
+
- Disappear when the selection is cleared.
|
|
163
|
+
|
|
164
|
+
### Combining Indicators
|
|
165
|
+
|
|
166
|
+
All indicators can appear simultaneously. The status bar shows whichever are relevant:
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
Rows: 1000 | Filtered: 250 | Selected: 3 | Cells: 8 | Sum: 12500 | Avg: 1562.50 | Min: 800 | Max: 3200 | Count: 8
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Advanced: Custom Status Bar Props
|
|
173
|
+
|
|
174
|
+
For full control, pass an `IStatusBarProps` object instead of `true`.
|
|
175
|
+
|
|
176
|
+
```tsx
|
|
177
|
+
<OGrid
|
|
178
|
+
columns={columns}
|
|
179
|
+
data={data}
|
|
180
|
+
getRowId={(r) => r.id}
|
|
181
|
+
statusBar={{
|
|
182
|
+
totalCount: data.length,
|
|
183
|
+
filteredCount: filteredData.length,
|
|
184
|
+
selectedCount: selectedRows.size,
|
|
185
|
+
panels: ['rowCount', 'filteredRowCount', 'selectedRowCount'],
|
|
186
|
+
}}
|
|
187
|
+
/>
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Props Reference
|
|
191
|
+
|
|
192
|
+
| Type | Field | Description |
|
|
193
|
+
|---|---|---|
|
|
194
|
+
| `IOGridProps<T>` | `statusBar` | `boolean` or `IStatusBarProps` |
|
|
195
|
+
| `IStatusBarProps` | `totalCount` | Total number of rows (unfiltered) |
|
|
196
|
+
| `IStatusBarProps` | `filteredCount` | Number of rows after filtering (omit to hide) |
|
|
197
|
+
| `IStatusBarProps` | `selectedCount` | Number of selected rows (omit or 0 to hide) |
|
|
198
|
+
| `IStatusBarProps` | `panels` | Array of panel IDs to show: `'rowCount'`, `'filteredRowCount'`, `'selectedRowCount'` |
|
|
199
|
+
| `IStatusBarProps` | `aggregation` | `{ sum, avg, min, max, count } \| null` for selected numeric cells |
|
|
200
|
+
|
|
201
|
+
## Related
|
|
202
|
+
|
|
203
|
+
- [CSV Export](./csv-export) -- export the data behind the counts
|
|
204
|
+
- [Server-Side Data](./server-side-data) -- status bar works with server-side `totalCount`
|
|
205
|
+
- [Keyboard Navigation](./keyboard-navigation) -- Shift+Arrow to select cell ranges for aggregation
|