@thkl/agrid 0.1.11 → 0.1.14
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 +169 -11
- package/fesm2022/thkl-agrid.mjs +3346 -624
- package/fesm2022/thkl-agrid.mjs.map +1 -1
- package/package.json +4 -4
- package/types/thkl-agrid.d.ts +1056 -62
- package/types/thkl-agrid.d.ts.map +1 -1
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @thkl/agrid
|
|
2
2
|
|
|
3
|
-
A signal-based, standalone data grid for Angular 21 with virtual scrolling, editing,
|
|
3
|
+
A signal-based, standalone data grid for Angular 21 and 22 with virtual scrolling, editing,
|
|
4
4
|
filtering, sorting, grouping, tree data, pinned columns, selection, clipboard operations,
|
|
5
|
-
and
|
|
5
|
+
pagination, and linked SVG charts/graphs.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -10,6 +10,16 @@ and pagination.
|
|
|
10
10
|
npm install @thkl/agrid @angular/cdk
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
+
## Feature Highlights
|
|
14
|
+
|
|
15
|
+
- Virtual rows and virtual columns for large and wide datasets.
|
|
16
|
+
- Text, value, quick, and condition filters with local or server-side workflows.
|
|
17
|
+
- Inline editing, validation, undo/redo, paste, fill, custom editors, and custom renderers.
|
|
18
|
+
- Range selection, selection summaries, row selection, row marking, column marking, and row numbers.
|
|
19
|
+
- Grouping, aggregate footers, tree data with descendant rollups, pivot tables, and master/detail rows.
|
|
20
|
+
- Pinned columns, pinned rows, column reordering, column autosize, and persistable settings.
|
|
21
|
+
- CSV, zero-dependency `.xlsx` export, sparklines, and linked SVG charts/graphs.
|
|
22
|
+
|
|
13
23
|
## Usage
|
|
14
24
|
|
|
15
25
|
```ts
|
|
@@ -72,14 +82,119 @@ be dragged.
|
|
|
72
82
|
`confirmRowDelete` protects grid delete actions with a localized in-row Yes/No confirmation.
|
|
73
83
|
Direct calls to `AgridDataSource.removeRow()` remain immediate.
|
|
74
84
|
|
|
75
|
-
`
|
|
76
|
-
|
|
85
|
+
`showRowNumbers` displays 1-based row numbers in the control column for the current filtered and
|
|
86
|
+
sorted row order. When row reordering is enabled, the number replaces the drag-handle glyph while
|
|
87
|
+
the control cell remains draggable.
|
|
88
|
+
|
|
89
|
+
`enableRowMarking` makes each control-cell row header clickable and adds a checkbox. Clicking the
|
|
90
|
+
header outside its nested controls toggles the same mark state and emits `(rowMark)` with the row,
|
|
91
|
+
its original datasource index, and the resulting `marked` state. Marked rows are included in
|
|
92
|
+
keyboard, cell-context, and row-context copy operations. Read `grid.markedRowIndices()` or call
|
|
77
93
|
`grid.clearMarkedRows()` when the host needs to inspect or reset the copy basket.
|
|
78
94
|
|
|
79
95
|
Marking is independent from row selection. Cell and range copy use the same copied columns for
|
|
80
96
|
every marked row, while Copy row uses every visible column. Duplicate rows are omitted, and marked
|
|
81
97
|
rows remain included when filters hide them.
|
|
82
98
|
|
|
99
|
+
Selecting numeric cells displays a live status bar with count, sum, average, minimum, and maximum.
|
|
100
|
+
Read the same values from `grid.selectionSummary()`. The signal is `null` when the active selection
|
|
101
|
+
contains no finite numeric values.
|
|
102
|
+
|
|
103
|
+
## Charts / Graphs
|
|
104
|
+
|
|
105
|
+
Use `AgridChartComponent` with an `AgridChartProvider` to render zero-dependency SVG graphs. The
|
|
106
|
+
same provider pattern as the grid keeps setup predictable:
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
import { AgridChartComponent, AgridChartProvider } from '@thkl/agrid';
|
|
110
|
+
|
|
111
|
+
readonly chartProvider = new AgridChartProvider({
|
|
112
|
+
type: 'column',
|
|
113
|
+
data: {
|
|
114
|
+
categories: ['Q1', 'Q2', 'Q3', 'Q4'],
|
|
115
|
+
series: [
|
|
116
|
+
{ name: 'North', values: [120, 145, 138, 162] },
|
|
117
|
+
{ name: 'South', values: [98, 110, 134, 128] },
|
|
118
|
+
],
|
|
119
|
+
},
|
|
120
|
+
height: 300,
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
```html
|
|
125
|
+
<agrid-chart [provider]="chartProvider" />
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Supported `type` values are `column`, `bar`, `line`, `area`, `pie`, and `donut`. `type`, `height`,
|
|
129
|
+
`showLegend`, `showAxis`, and `palette` are signals, so runtime changes redraw immediately.
|
|
130
|
+
|
|
131
|
+
To link a graph to a grid, pass `provider.visibleRows` as `source` and provide a `transform`. The
|
|
132
|
+
chart follows filtering, sorting, and edits live:
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
readonly chartProvider = new AgridChartProvider<Person>({
|
|
136
|
+
type: 'bar',
|
|
137
|
+
source: this.provider.visibleRows,
|
|
138
|
+
transform: rows => ({
|
|
139
|
+
categories: rows.map(row => row.name),
|
|
140
|
+
series: [{ name: 'Score', values: rows.map(row => Number(row.score ?? 0)) }],
|
|
141
|
+
}),
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
`visibleRows` is the filtered and sorted row set. It intentionally ignores grouping and pagination;
|
|
146
|
+
aggregate inside `transform` when the graph should show grouped totals or page-specific summaries.
|
|
147
|
+
Pie and donut graphs use the first series and label slices from `categories`.
|
|
148
|
+
|
|
149
|
+
Set `enableColumnMarking: true` to toggle complete-column highlighting by clicking a header outside
|
|
150
|
+
its menu and resize controls. The grid exposes `markedColumnFields()` and emits `(columnMark)`.
|
|
151
|
+
|
|
152
|
+
Append custom commands to one column's menu and handle them through one typed output:
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
{ field: 'status', header: 'Status', headerMenuItems: [
|
|
156
|
+
{ key: 'archive', label: 'Archive', icon: '⌂' },
|
|
157
|
+
] }
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
```html
|
|
161
|
+
<agrid [provider]="provider" (columnHeaderAction)="onColumnHeaderAction($event)" />
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
The event contains `{ column, key }`.
|
|
165
|
+
|
|
166
|
+
Use `(firstDataRendered)` when host logic must wait until the grid has completed its first render
|
|
167
|
+
containing datasource rows:
|
|
168
|
+
|
|
169
|
+
```html
|
|
170
|
+
<agrid [provider]="provider" (firstDataRendered)="onGridReady($event)" />
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
The event fires once per grid component. An initially empty datasource delays it until rows arrive.
|
|
174
|
+
Server-side loading placeholders do not count as rendered data. The payload contains `rows`,
|
|
175
|
+
`rowCount`, `provider`, and `datasource`.
|
|
176
|
+
|
|
177
|
+
For commands that change `textAlign` at runtime, keep the writable signal in the host instead of
|
|
178
|
+
mutating `event.column`:
|
|
179
|
+
|
|
180
|
+
```ts
|
|
181
|
+
readonly salaryAlignment = signal<'left' | 'center' | 'right'>('right');
|
|
182
|
+
|
|
183
|
+
// Column definition
|
|
184
|
+
{ field: 'salary', header: 'Salary', textAlign: this.salaryAlignment }
|
|
185
|
+
|
|
186
|
+
onColumnHeaderAction(event: ColumnHeaderActionEvent<Employee>): void {
|
|
187
|
+
if (event.column.field !== 'salary') return;
|
|
188
|
+
if (event.key === 'align-left') this.salaryAlignment.set('left');
|
|
189
|
+
if (event.key === 'align-center') this.salaryAlignment.set('center');
|
|
190
|
+
if (event.key === 'align-right') this.salaryAlignment.set('right');
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Assigning `event.column.textAlign = 'center'` mutates plain configuration and does not trigger an
|
|
195
|
+
Angular update. Calling `.set()` on `event.column.textAlign` is also not type-safe because the
|
|
196
|
+
property may contain a static string or a read-only signal.
|
|
197
|
+
|
|
83
198
|
## Menu bar
|
|
84
199
|
|
|
85
200
|
Set `menuBarItems` to render command buttons above the headers. An item with `items` becomes a
|
|
@@ -112,6 +227,9 @@ readonly provider = new AgridProvider<Person>({
|
|
|
112
227
|
`visible`, `active`, and `disabled` may be booleans or callbacks. Callback context includes
|
|
113
228
|
`rows`, `selectedRows`, `selectedCell`, `provider`, and `datasource`.
|
|
114
229
|
|
|
230
|
+
For imperative selection reads, call `grid.getCurrentRow()` or `grid.getCurrentCell()`. The
|
|
231
|
+
`(cellSelect)` output emits the same selected-cell shape and `null` when cell selection clears.
|
|
232
|
+
|
|
115
233
|
## Input masks
|
|
116
234
|
|
|
117
235
|
Use `inputMask` to select a string mask for each row and cell. The callback
|
|
@@ -171,6 +289,10 @@ does not include. Numbers offer `=`, `≠`, `>`, `≥`, `<`, `≤`, and `between
|
|
|
171
289
|
before / after / between. Conditions combine with the header text filter, value picker, and other
|
|
172
290
|
columns using AND semantics, and are included in `AgridControl.toJSON()` state.
|
|
173
291
|
|
|
292
|
+
The header arrow opens the complete column menu. The condition button beside the inline filter
|
|
293
|
+
opens only the condition operator and operand controls; sorting, layout, grouping, custom commands,
|
|
294
|
+
clear-all actions, and distinct-value selection remain in the complete menu.
|
|
295
|
+
|
|
174
296
|
```ts
|
|
175
297
|
const columns: ColDef<Order>[] = [
|
|
176
298
|
{ field: 'reference', header: 'Reference', filterable: true },
|
|
@@ -219,15 +341,40 @@ readonly provider = new AgridProvider<Person>({ columns, datasource, enableQuick
|
|
|
219
341
|
Drive it programmatically with `control.setQuickFilter(text)`; it's part of `toJSON()` state and is
|
|
220
342
|
cleared by `control.clearAllFilters()`.
|
|
221
343
|
|
|
344
|
+
Use `control.getFilterModel()` and `control.setFilterModel(model)` to persist or restore just the
|
|
345
|
+
filter, quick-filter, and sort state without the rest of the grid settings.
|
|
346
|
+
|
|
347
|
+
Rows inserted while filters or sorts are active stay visible in insertion order even if their values
|
|
348
|
+
do not currently match. Wire `control.reapplyFilters()` to a button or save action when those
|
|
349
|
+
inserted rows should be filtered and sorted like the rest of the datasource again. Use
|
|
350
|
+
`control.filterReapplyNeeded()` to show visual feedback when that action is available.
|
|
351
|
+
|
|
222
352
|
## Server-side filtering
|
|
223
353
|
|
|
224
|
-
With `serverSideFiltering: true` the grid never filters locally
|
|
225
|
-
|
|
354
|
+
With `serverSideFiltering: true` the grid never filters locally. The recommended integration point
|
|
355
|
+
is the complete query snapshot:
|
|
356
|
+
|
|
357
|
+
```html
|
|
358
|
+
<agrid [provider]="provider" (serverQueryChange)="loadRows($event)" />
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
```ts
|
|
362
|
+
effect(() => {
|
|
363
|
+
const query = provider.serverQuery();
|
|
364
|
+
if (!query) return;
|
|
365
|
+
store.load(query);
|
|
366
|
+
});
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
`AgridServerQuery` contains column filters, value selections, menu conditions, ordered sorts,
|
|
370
|
+
quick-filter text, and page range (`startRow..endRow`, inclusive). The older granular outputs remain
|
|
371
|
+
available for compatibility:
|
|
226
372
|
|
|
227
|
-
- `(filterChange)` — header text filters emit `{ field, value }`;
|
|
373
|
+
- `(filterChange)` — header text filters emit `{ field, value }`; value filters emit
|
|
374
|
+
`{ field, value: '', selectedValues }`; menu conditions emit
|
|
228
375
|
`{ field, value: '', operator, operand, operand2 }` (operator `null` clears the condition).
|
|
229
376
|
- `(sortChange)` — `{ field, direction }`.
|
|
230
|
-
- `(quickFilterChange)` — the quick-filter text
|
|
377
|
+
- `(quickFilterChange)` — the quick-filter text.
|
|
231
378
|
|
|
232
379
|
```html
|
|
233
380
|
<agrid [provider]="provider"
|
|
@@ -237,7 +384,7 @@ refetch:
|
|
|
237
384
|
```
|
|
238
385
|
|
|
239
386
|
Text/range/quick events are debounced by `filterDebounceMs` (default 300 ms; `0` disables). The
|
|
240
|
-
|
|
387
|
+
distinct-value picker is hidden in this mode unless the column supplies an explicit `values`
|
|
241
388
|
list representing the complete server-side value set.
|
|
242
389
|
|
|
243
390
|
## Grouping and aggregates
|
|
@@ -316,6 +463,14 @@ tree.
|
|
|
316
463
|
Tree mode can be combined with `masterDetail: true` and a `detailRenderer`. Detail expanders are
|
|
317
464
|
shown only for leaf rows; parent rows retain their tree expand/collapse control.
|
|
318
465
|
|
|
466
|
+
Set `detailColumnField` to a column field when the panel should expose one larger multiline value.
|
|
467
|
+
The formatted value is shown normally; click it or focus it and press Enter to open a textarea.
|
|
468
|
+
Blur or Ctrl/Cmd+Enter commits, while Escape cancels. Editability, validation, history, and edit
|
|
469
|
+
events follow the linked column's normal cell behavior.
|
|
470
|
+
Set `detailActions` to add text-template buttons above the textarea. Each action has an `id`,
|
|
471
|
+
`label`, and optional `text` string or row-aware resolver; clicking inserts at the current
|
|
472
|
+
selection, or appends if the button opens the textarea.
|
|
473
|
+
|
|
319
474
|
## Standalone tree control
|
|
320
475
|
|
|
321
476
|
Use `<agrid-tree>` for the same parent-ID or path hierarchy without grid columns. It adds tree
|
|
@@ -453,7 +608,8 @@ Use `rowChanged` to send one request after the user edits one or more fields in
|
|
|
453
608
|
```ts
|
|
454
609
|
saveRow(event: RowUpdateEvent<Person>): void {
|
|
455
610
|
this.http.patch(`/api/people/${event.row.id}`, event.row).subscribe(() => {
|
|
456
|
-
this.
|
|
611
|
+
this.provider.control.indicate(event.originalIndex, '#2da44e', 1000);
|
|
612
|
+
this.provider.control.clearChangedCells(event.originalIndex);
|
|
457
613
|
});
|
|
458
614
|
}
|
|
459
615
|
```
|
|
@@ -461,6 +617,8 @@ saveRow(event: RowUpdateEvent<Person>): void {
|
|
|
461
617
|
The event fires with the latest complete row when inline navigation leaves that row, or when the
|
|
462
618
|
sidebar editor Save button is used. `cellEdit` and `recordEdit` remain available for every committed
|
|
463
619
|
field change. With `showChangedCellIndicator: true`, changed cells keep a corner marker until the
|
|
464
|
-
PATCH succeeds. Override `--agrid-color-cell-changed` to customize its color.
|
|
620
|
+
PATCH succeeds. Override `--agrid-color-cell-changed` to customize its color. Call
|
|
621
|
+
`control.indicate(index, color, durationMs)` to flash a complete row for transient server-side
|
|
622
|
+
feedback.
|
|
465
623
|
|
|
466
624
|
Full documentation and demos: https://thkl.github.io/agrid/
|