@thkl/agrid 0.1.5 → 0.1.7

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 CHANGED
@@ -71,6 +71,112 @@ Marking is independent from row selection. Cell and range copy use the same copi
71
71
  every marked row, while Copy row uses every visible column. Duplicate rows are omitted, and marked
72
72
  rows remain included when filters hide them.
73
73
 
74
+ ## Boolean columns
75
+
76
+ Set `type: 'boolean'` to render a cell as an inline checkbox. Clicking it toggles the value and
77
+ commits immediately — no edit mode, and the change is recorded in undo/redo like any other edit.
78
+ Read-only columns (`editable: false`) or a read-only grid render the checkbox disabled. Values are
79
+ truthy-coerced for display, so `true`, `1`, `'true'`, and `'1'` all render as checked.
80
+
81
+ ```ts
82
+ const columns: ColDef<Person>[] = [
83
+ { field: 'name', header: 'Name' },
84
+ { field: 'active', header: 'Active', type: 'boolean' },
85
+ ];
86
+ ```
87
+
88
+ ## Typed filters
89
+
90
+ Mark a `number` or `date` column `filterable: true` and its column menu gains a **condition**
91
+ filter in addition to the value picker. Numbers offer `=`, `≠`, `>`, `≥`, `<`, `≤`, and `between`;
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.
94
+
95
+ ```ts
96
+ const columns: ColDef<Order>[] = [
97
+ { field: 'total', header: 'Total', type: 'number', filterable: true },
98
+ { field: 'placedAt', header: 'Placed', type: 'date', filterable: true },
99
+ ];
100
+ ```
101
+
102
+ Set it programmatically with `control.setRangeFilter(field, operator, operand, operand2?)`, where
103
+ `operator` is one of `'eq' | 'neq' | 'gt' | 'gte' | 'lt' | 'lte' | 'between'` (pass `null` to clear).
104
+
105
+ ## Edit validation
106
+
107
+ Add a `validate` hook to a column to reject bad values. Return a message to block the edit (the
108
+ value is not written and the message is shown), or `null` to accept it. It runs on inline commit,
109
+ boolean-checkbox toggle, and sidebar save.
110
+
111
+ ```ts
112
+ const columns: ColDef<Person>[] = [
113
+ { field: 'email', header: 'Email',
114
+ validate: v => /@/.test(String(v)) ? null : 'Enter a valid email' },
115
+ { field: 'age', header: 'Age', type: 'number',
116
+ validate: (v, row) => Number(v) >= 0 ? null : 'Age must be ≥ 0' },
117
+ ];
118
+ ```
119
+
120
+ A rejected inline edit keeps the cell in edit mode with the message shown beneath it, so the user
121
+ can correct it; Tab/Enter won't leave the cell until the value is valid. Rejected sidebar edits show
122
+ the message under the field. Listen to `(validationFailed)` for `{ rowIndex, field, value, message,
123
+ source }` (`source` is `'inline'` or `'sidebar'`).
124
+
125
+ ```html
126
+ <agrid [provider]="provider" (validationFailed)="onInvalid($event)" />
127
+ ```
128
+
129
+ ## Quick filter
130
+
131
+ Set `enableQuickFilter: true` to render a search box above the grid that keeps rows whose visible
132
+ columns contain the text (resolved display values, so `ValueOption` labels and formatters count).
133
+
134
+ ```ts
135
+ readonly provider = new AgridProvider<Person>({ columns, datasource, enableQuickFilter: true });
136
+ ```
137
+
138
+ Drive it programmatically with `control.setQuickFilter(text)`; it's part of `toJSON()` state and is
139
+ cleared by `control.clearAllFilters()`.
140
+
141
+ ## Server-side filtering
142
+
143
+ With `serverSideFiltering: true` the grid never filters locally — it emits events so the host can
144
+ refetch:
145
+
146
+ - `(filterChange)` — text filters emit `{ field, value }`; typed range conditions emit
147
+ `{ field, value: '', operator, operand, operand2 }` (operator `null` clears the condition).
148
+ - `(sortChange)` — `{ field, direction }`.
149
+ - `(quickFilterChange)` — the quick-filter text (debounced by `filterDebounceMs`).
150
+
151
+ ```html
152
+ <agrid [provider]="provider"
153
+ (filterChange)="onFilter($event)"
154
+ (sortChange)="onSort($event)"
155
+ (quickFilterChange)="onQuickFilter($event)" />
156
+ ```
157
+
158
+ Text/range/quick events are debounced by `filterDebounceMs` (default 300 ms; `0` disables). The
159
+ Excel-style value picker stays client-only and is hidden in this mode.
160
+
161
+ ## Grouping and aggregates
162
+
163
+ Give a column an `aggregate` (`'sum'`, `'avg'`, `'min'`, `'max'`, `'count'`, or a custom
164
+ `(values) => unknown` function) and the grid renders a footer row with that column's total over all
165
+ filtered rows. Set/clear it at runtime with `control.setAggregate(field, fn)`.
166
+
167
+ ```ts
168
+ const columns: ColDef<Order>[] = [
169
+ { field: 'region', header: 'Region', groupable: true },
170
+ { field: 'total', header: 'Total', type: 'number', aggregate: 'sum' },
171
+ ];
172
+ ```
173
+
174
+ When the grid is grouped (set `groupable: true` and group from the column menu, or call
175
+ `control.setGroupBy(field)`), each **group header row also shows that group's subtotals** —
176
+ the same aggregate functions applied to just the group's rows, displayed inline beside the group
177
+ label and count. No extra configuration is needed; subtotals appear whenever grouping and at least
178
+ one aggregated column are both active.
179
+
74
180
  ## Tree data
75
181
 
76
182
  Pass `treeConfig` to render rows as a hierarchical tree. The hierarchy lives on the flat row