@thkl/agrid 0.1.7 → 0.1.10
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 +1811 -167
- package/fesm2022/thkl-agrid.mjs.map +1 -1
- package/package.json +3 -3
- package/types/thkl-agrid.d.ts +601 -30
- package/types/thkl-agrid.d.ts.map +1 -1
package/README.md
CHANGED
|
@@ -30,7 +30,12 @@ interface Person {
|
|
|
30
30
|
|
|
31
31
|
const columns: ColDef<Person>[] = [
|
|
32
32
|
{ field: 'id', header: 'ID', editable: false },
|
|
33
|
-
{
|
|
33
|
+
{
|
|
34
|
+
field: 'name',
|
|
35
|
+
header: 'Name',
|
|
36
|
+
filterable: true,
|
|
37
|
+
infoIcon: ({ row }) => Boolean(row.name),
|
|
38
|
+
},
|
|
34
39
|
];
|
|
35
40
|
|
|
36
41
|
@Component({
|
|
@@ -55,6 +60,10 @@ export class PeopleComponent {
|
|
|
55
60
|
}
|
|
56
61
|
```
|
|
57
62
|
|
|
63
|
+
Set `infoIcon: true` to show a right-aligned `?` action for every cell in a
|
|
64
|
+
column, or use a predicate to enable it per row. Listen to `(cellInfo)` to
|
|
65
|
+
receive the row, field, value, original row index, and column definition.
|
|
66
|
+
|
|
58
67
|
Set `group: 'employee'` on adjacent columns to render the `Employee` label above them. Dragging
|
|
59
68
|
that grouped header moves its current contiguous column segment as one block. Reordering, hiding,
|
|
60
69
|
or pinning may split one group ID into multiple headers. Segments containing locked columns cannot
|
|
@@ -71,6 +80,59 @@ Marking is independent from row selection. Cell and range copy use the same copi
|
|
|
71
80
|
every marked row, while Copy row uses every visible column. Duplicate rows are omitted, and marked
|
|
72
81
|
rows remain included when filters hide them.
|
|
73
82
|
|
|
83
|
+
## Menu bar
|
|
84
|
+
|
|
85
|
+
Set `menuBarItems` to render command buttons above the headers. An item with `items` becomes a
|
|
86
|
+
split button: its label emits the parent id and its chevron opens additional commands. Every
|
|
87
|
+
command emits through the single `(menuBarAction)` output.
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
readonly provider = new AgridProvider<Person>({
|
|
91
|
+
columns,
|
|
92
|
+
datasource,
|
|
93
|
+
menuBarItems: [
|
|
94
|
+
{ id: 'refresh', label: 'Refresh', icon: '↻' },
|
|
95
|
+
{
|
|
96
|
+
id: 'selection',
|
|
97
|
+
label: 'Selection',
|
|
98
|
+
disabled: ({ selectedRows }) => selectedRows.length === 0,
|
|
99
|
+
items: [
|
|
100
|
+
{ id: 'activate', label: 'Activate' },
|
|
101
|
+
{ id: 'deactivate', label: 'Deactivate', active: ({ rows }) => rows.some(row => !row.active) },
|
|
102
|
+
],
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
});
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
```html
|
|
109
|
+
<agrid [provider]="provider" (menuBarAction)="runCommand($event)" />
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`visible`, `active`, and `disabled` may be booleans or callbacks. Callback context includes
|
|
113
|
+
`rows`, `selectedRows`, `selectedCell`, `provider`, and `datasource`.
|
|
114
|
+
|
|
115
|
+
## Input masks
|
|
116
|
+
|
|
117
|
+
Use `inputMask` to select a string mask for each row and cell. The callback
|
|
118
|
+
receives `{ row, value, column }`; return `null` for cells that should remain
|
|
119
|
+
unrestricted.
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
{
|
|
123
|
+
field: 'reference',
|
|
124
|
+
header: 'Reference',
|
|
125
|
+
inputMask: ({ row }) =>
|
|
126
|
+
row.numeric
|
|
127
|
+
? /\d{0,3}(?:-\d{0,5}(?:-\d{0,5})?)?/
|
|
128
|
+
: /[a-z0-9]{0,3}(?: [a-z0-9]{0,3}(?: [a-z0-9]{0,5})?)?/i,
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The regex is matched against the complete proposed value and must allow
|
|
133
|
+
partial input. Separators are typed explicitly rather than inserted
|
|
134
|
+
automatically. Invalid edits revert to the last accepted value.
|
|
135
|
+
|
|
74
136
|
## Boolean columns
|
|
75
137
|
|
|
76
138
|
Set `type: 'boolean'` to render a cell as an inline checkbox. Clicking it toggles the value and
|
|
@@ -85,22 +147,41 @@ const columns: ColDef<Person>[] = [
|
|
|
85
147
|
];
|
|
86
148
|
```
|
|
87
149
|
|
|
88
|
-
##
|
|
150
|
+
## Runtime readonly cells
|
|
89
151
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
dates offer on / before / after / between. The condition combines with the value picker and other
|
|
93
|
-
columns using AND semantics, and is included in `AgridControl.toJSON()` state.
|
|
152
|
+
Use `cellReadonly` when editability depends on the current row. Returning `true` blocks inline
|
|
153
|
+
editing, boolean toggles, paste, fill, and sidebar edits for that cell.
|
|
94
154
|
|
|
95
155
|
```ts
|
|
96
156
|
const columns: ColDef<Order>[] = [
|
|
157
|
+
{ field: 'status', header: 'Status' },
|
|
158
|
+
{
|
|
159
|
+
field: 'approvedBy',
|
|
160
|
+
header: 'Approved by',
|
|
161
|
+
cellReadonly: ({ row }) => row.status !== 'Draft',
|
|
162
|
+
},
|
|
163
|
+
];
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Condition filters
|
|
167
|
+
|
|
168
|
+
Mark a column `filterable: true` and its column menu gains a **condition** filter in addition to
|
|
169
|
+
the value picker. Text columns offer equals, not equal, like, starts with, ends with, includes, and
|
|
170
|
+
does not include. Numbers offer `=`, `≠`, `>`, `≥`, `<`, `≤`, and `between`; dates offer on /
|
|
171
|
+
before / after / between. Conditions combine with the header text filter, value picker, and other
|
|
172
|
+
columns using AND semantics, and are included in `AgridControl.toJSON()` state.
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
const columns: ColDef<Order>[] = [
|
|
176
|
+
{ field: 'reference', header: 'Reference', filterable: true },
|
|
97
177
|
{ field: 'total', header: 'Total', type: 'number', filterable: true },
|
|
98
178
|
{ field: 'placedAt', header: 'Placed', type: 'date', filterable: true },
|
|
99
179
|
];
|
|
100
180
|
```
|
|
101
181
|
|
|
102
182
|
Set it programmatically with `control.setRangeFilter(field, operator, operand, operand2?)`, where
|
|
103
|
-
`operator`
|
|
183
|
+
`operator` can also be `'like' | 'startsWith' | 'endsWith' | 'includes' | 'notIncludes'` for text
|
|
184
|
+
columns (pass `null` to clear). `like` uses `%` for any sequence and `_` for one character.
|
|
104
185
|
|
|
105
186
|
## Edit validation
|
|
106
187
|
|
|
@@ -143,7 +224,7 @@ cleared by `control.clearAllFilters()`.
|
|
|
143
224
|
With `serverSideFiltering: true` the grid never filters locally — it emits events so the host can
|
|
144
225
|
refetch:
|
|
145
226
|
|
|
146
|
-
- `(filterChange)` — text filters emit `{ field, value }`;
|
|
227
|
+
- `(filterChange)` — header text filters emit `{ field, value }`; menu conditions emit
|
|
147
228
|
`{ field, value: '', operator, operand, operand2 }` (operator `null` clears the condition).
|
|
148
229
|
- `(sortChange)` — `{ field, direction }`.
|
|
149
230
|
- `(quickFilterChange)` — the quick-filter text (debounced by `filterDebounceMs`).
|
|
@@ -179,9 +260,8 @@ one aggregated column are both active.
|
|
|
179
260
|
|
|
180
261
|
## Tree data
|
|
181
262
|
|
|
182
|
-
Pass `treeConfig` to render rows as a hierarchical tree.
|
|
183
|
-
|
|
184
|
-
selection and editing keep working on the same indices.
|
|
263
|
+
Pass `treeConfig` to render rows as a hierarchical tree. Use stable `id` / `parentId` accessors
|
|
264
|
+
for an existing hierarchy, or `getPath` to generate display-only branches from each row.
|
|
185
265
|
|
|
186
266
|
```ts
|
|
187
267
|
import { AgridTreeConfig } from '@thkl/agrid';
|
|
@@ -199,12 +279,90 @@ readonly provider = new AgridProvider<OrgRow>({
|
|
|
199
279
|
});
|
|
200
280
|
```
|
|
201
281
|
|
|
282
|
+
For path-like values such as `01.01.0001`, return the ordered segments:
|
|
283
|
+
|
|
284
|
+
```ts
|
|
285
|
+
const treeConfig: AgridTreeConfig<Row> = {
|
|
286
|
+
getPath: row => row.oz.split('.'),
|
|
287
|
+
nodeUuid: row => row.uuid,
|
|
288
|
+
formatPathSegment: ({ row, segment, level, leaf }) =>
|
|
289
|
+
leaf
|
|
290
|
+
? `${segment} ${row.description}`
|
|
291
|
+
: `${segment} ${level === 0 ? row.areaLabel : row.groupLabel}`,
|
|
292
|
+
treeField: 'oz',
|
|
293
|
+
};
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
This renders `01 / 01 / 0001, 0002`. Generated `01` branch rows are display-only; the leaf remains
|
|
297
|
+
the original datasource row. Its tree cell displays `0001`, while editing still uses the complete
|
|
298
|
+
`01.01.0001` value. `formatPathSegment` changes labels only; raw segments still control grouping,
|
|
299
|
+
expansion identity, and sort order. The callback receives the original `row`; shared branch nodes
|
|
300
|
+
use the first row encountered for that raw path prefix. `nodeUuid` uses the same source row and is
|
|
301
|
+
included in generated branch-node click events.
|
|
302
|
+
|
|
202
303
|
The `treeField` column shows an indented expand/collapse twisty. Filtering and sorting behave as
|
|
203
304
|
in a flat grid; with `keepAncestorsOnFilter` (default `true`) a match deep in the tree keeps its
|
|
204
305
|
parents visible and force-opens the path to it. Tree mode takes precedence over grouping and
|
|
205
306
|
disables pagination. Call `grid.expandAllNodes()` / `grid.collapseAllNodes()` to toggle the whole
|
|
206
307
|
tree.
|
|
207
308
|
|
|
309
|
+
Tree mode can be combined with `masterDetail: true` and a `detailRenderer`. Detail expanders are
|
|
310
|
+
shown only for leaf rows; parent rows retain their tree expand/collapse control.
|
|
311
|
+
|
|
312
|
+
## Standalone tree control
|
|
313
|
+
|
|
314
|
+
Use `<agrid-tree>` for the same parent-ID or path hierarchy without grid columns. It adds tree
|
|
315
|
+
keyboard navigation and optional single or multi-selection.
|
|
316
|
+
|
|
317
|
+
```ts
|
|
318
|
+
readonly treeProvider = new AgridTreeProvider<OrgRow>({
|
|
319
|
+
datasource: new AgridDataSource(rows),
|
|
320
|
+
treeConfig: {
|
|
321
|
+
getId: row => row.id,
|
|
322
|
+
getParentId: row => row.parentId,
|
|
323
|
+
treeField: 'name',
|
|
324
|
+
defaultExpanded: true,
|
|
325
|
+
},
|
|
326
|
+
getDescription: row => row.role,
|
|
327
|
+
selection: 'single',
|
|
328
|
+
ariaLabel: 'Organization',
|
|
329
|
+
});
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
```html
|
|
333
|
+
<agrid-tree [provider]="treeProvider"
|
|
334
|
+
(nodeClick)="openNode($event)"
|
|
335
|
+
(nodeDoubleClicked)="openNode($event)"
|
|
336
|
+
(selectionChange)="selectionChanged($event)" />
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
Row and generated path-branch clicks emit `AgridTreeNodeEvent<T>`. Branch events include their
|
|
340
|
+
configured or generated `uuid`. `expandAllNodes()` and `collapseAllNodes()` are public methods.
|
|
341
|
+
The tree uses the shared `--agrid-color-text`, `--agrid-color-text-muted`,
|
|
342
|
+
`--agrid-color-accent`, `--agrid-color-accent-subtle`, `--agrid-color-accent-fg`,
|
|
343
|
+
`--agrid-color-border`, `--agrid-color-bg`, and `--agrid-color-bg-muted` CSS variables.
|
|
344
|
+
|
|
345
|
+
## Page selector
|
|
346
|
+
|
|
347
|
+
Use `<agrid-page-selector>` to navigate pages by previous/next button, dropdown, or typed ID.
|
|
348
|
+
All three interactions emit an `AgridPageItem<TId>` through the single `(selectPage)` output.
|
|
349
|
+
|
|
350
|
+
```ts
|
|
351
|
+
readonly pages: AgridPageItem<number>[] = [
|
|
352
|
+
{ id: 1, label: 'Cover' },
|
|
353
|
+
{ id: 2, label: 'Measurements' },
|
|
354
|
+
{ id: 3, label: 'Summary' },
|
|
355
|
+
];
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
```html
|
|
359
|
+
<agrid-page-selector [items]="pages" [selectedId]="currentPageId()"
|
|
360
|
+
(selectPage)="currentPageId.set($event.id)" />
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
IDs can be strings or numbers. Typed IDs are selected with Enter. Available inputs are
|
|
364
|
+
`disabled`, `previousLabel`, `nextLabel`, `inputLabel`, `menuLabel`, and `emptyText`.
|
|
365
|
+
|
|
208
366
|
## Saving edited rows
|
|
209
367
|
|
|
210
368
|
Use `rowChanged` to send one request after the user edits one or more fields in a row:
|