neo.mjs 10.0.0-beta.2 → 10.0.0-beta.4
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/.github/RELEASE_NOTES/v10.0.0-beta.4.md +41 -0
- package/ServiceWorker.mjs +2 -2
- package/apps/form/view/FormPageContainer.mjs +2 -3
- package/apps/portal/index.html +1 -1
- package/apps/portal/view/ViewportController.mjs +1 -1
- package/apps/portal/view/home/FooterContainer.mjs +1 -1
- package/apps/portal/view/learn/ContentComponent.mjs +18 -11
- package/apps/portal/view/learn/MainContainerController.mjs +6 -6
- package/learn/README.md +9 -14
- package/learn/guides/datahandling/Collections.md +436 -0
- package/learn/guides/datahandling/Grids.md +621 -0
- package/learn/guides/datahandling/Records.md +287 -0
- package/learn/guides/{StateProviders.md → datahandling/StateProviders.md} +145 -1
- package/learn/guides/fundamentals/ExtendingNeoClasses.md +359 -0
- package/learn/guides/uibuildingblocks/CustomComponents.md +287 -0
- package/learn/guides/uibuildingblocks/Layouts.md +248 -0
- package/learn/guides/userinteraction/Forms.md +449 -0
- package/learn/guides/userinteraction/form_fields/ComboBox.md +241 -0
- package/learn/tree.json +63 -52
- package/package.json +2 -2
- package/resources/scss/src/apps/portal/learn/ContentComponent.scss +9 -0
- package/src/DefaultConfig.mjs +2 -2
- package/src/Neo.mjs +37 -29
- package/src/collection/Base.mjs +29 -2
- package/src/component/Base.mjs +6 -16
- package/src/controller/Base.mjs +87 -63
- package/src/core/Base.mjs +72 -17
- package/src/core/Compare.mjs +3 -13
- package/src/core/Config.mjs +139 -0
- package/src/core/ConfigSymbols.mjs +3 -0
- package/src/core/Util.mjs +3 -18
- package/src/data/RecordFactory.mjs +22 -3
- package/src/form/field/ComboBox.mjs +6 -1
- package/src/util/Function.mjs +52 -5
- package/src/vdom/Helper.mjs +7 -5
- package/test/siesta/tests/ReactiveConfigs.mjs +112 -0
- package/learn/guides/CustomComponents.md +0 -45
- package/learn/guides/Forms.md +0 -1
- package/learn/guides/Layouts.md +0 -1
- /package/learn/guides/{Tables.md → datahandling/Tables.md} +0 -0
- /package/learn/guides/{ApplicationBootstrap.md → fundamentals/ApplicationBootstrap.md} +0 -0
- /package/learn/guides/{ConfigSystemDeepDive.md → fundamentals/ConfigSystemDeepDive.md} +0 -0
- /package/learn/guides/{DeclarativeComponentTreesVsImperativeVdom.md → fundamentals/DeclarativeComponentTreesVsImperativeVdom.md} +0 -0
- /package/learn/guides/{InstanceLifecycle.md → fundamentals/InstanceLifecycle.md} +0 -0
- /package/learn/guides/{MainThreadAddons.md → fundamentals/MainThreadAddons.md} +0 -0
- /package/learn/guides/{Mixins.md → specificfeatures/Mixins.md} +0 -0
- /package/learn/guides/{MultiWindow.md → specificfeatures/MultiWindow.md} +0 -0
- /package/learn/guides/{PortalApp.md → specificfeatures/PortalApp.md} +0 -0
- /package/learn/guides/{ComponentsAndContainers.md → uibuildingblocks/ComponentsAndContainers.md} +0 -0
- /package/learn/guides/{WorkingWithVDom.md → uibuildingblocks/WorkingWithVDom.md} +0 -0
- /package/learn/guides/{events → userinteraction/events}/CustomEvents.md +0 -0
- /package/learn/guides/{events → userinteraction/events}/DomEvents.md +0 -0
@@ -0,0 +1,621 @@
|
|
1
|
+
# Neo.mjs Grids
|
2
|
+
|
3
|
+
The `Neo.grid.Container` is a powerful and highly performant component for displaying tabular data. It is designed to
|
4
|
+
handle large datasets with ease, thanks to its virtual rendering engine, which only renders the DOM for the visible
|
5
|
+
rows and columns.
|
6
|
+
|
7
|
+
## Key Features
|
8
|
+
|
9
|
+
- **High Performance:** Optimized for handling large amounts of data through virtual rendering.
|
10
|
+
- **Flexible Data Model:** Integrates seamlessly with `Neo.data.Store` and `Neo.data.Model`.
|
11
|
+
- **Rich Column Types:** Supports various column types, including component-based columns.
|
12
|
+
- **Advanced Selection Models:** Offers a variety of selection models for rows, cells, and columns.
|
13
|
+
- **Sorting and Filtering:** Built-in support for column sorting and data filtering, including header filters.
|
14
|
+
- **Cell Editing:** Built-in support for editing cell values directly within the grid.
|
15
|
+
- **Customizable:** Easily extendable and customizable to fit your needs.
|
16
|
+
|
17
|
+
## Basic Grid Setup
|
18
|
+
|
19
|
+
Creating a grid is straightforward. You need a `Neo.grid.Container`, define your `columns`, and provide a `store`.
|
20
|
+
|
21
|
+
```javascript live-preview
|
22
|
+
import GridContainer from '../grid/Container.mjs';
|
23
|
+
import Store from '../data/Store.mjs';
|
24
|
+
import Viewport from '../container/Viewport.mjs';
|
25
|
+
|
26
|
+
class MainView extends Viewport {
|
27
|
+
static config = {
|
28
|
+
className: 'MainView',
|
29
|
+
layout : {ntype: 'fit'},
|
30
|
+
items : [{
|
31
|
+
module: GridContainer,
|
32
|
+
store : { // Inline store configuration
|
33
|
+
model: {
|
34
|
+
fields: [
|
35
|
+
{name: 'firstname', type: 'String'},
|
36
|
+
{name: 'lastname', type: 'String'}
|
37
|
+
]
|
38
|
+
},
|
39
|
+
data: [
|
40
|
+
{firstname: 'Tobias', lastname: 'Uhlig'},
|
41
|
+
{firstname: 'Rich', lastname: 'Waters'}
|
42
|
+
]
|
43
|
+
},
|
44
|
+
columns: [
|
45
|
+
{text: 'Firstname', dataField: 'firstname'},
|
46
|
+
{text: 'Lastname', dataField: 'lastname'}
|
47
|
+
]
|
48
|
+
}]
|
49
|
+
}
|
50
|
+
}
|
51
|
+
MainView = Neo.setupClass(MainView);
|
52
|
+
```
|
53
|
+
|
54
|
+
In this example, we create a simple grid with two columns. The `dataField` in each column configuration maps to a
|
55
|
+
field in the store's model. You can further customize the grid's behavior and appearance
|
56
|
+
by providing `bodyConfig` and `headerToolbarConfig`.
|
57
|
+
|
58
|
+
## Integrating with Stores
|
59
|
+
|
60
|
+
The `store` config is central to the `Neo.grid.Container`, as it provides the data to be displayed.
|
61
|
+
You have several flexible ways to define and provide a store:
|
62
|
+
|
63
|
+
### 1. Inline Store Configuration (Plain JavaScript Object)
|
64
|
+
|
65
|
+
This is the most common approach for simple grids, where the store's model and data are defined directly within the
|
66
|
+
grid's configuration. The grid automatically creates a `Neo.data.Store` instance from this object.
|
67
|
+
|
68
|
+
```javascript readonly
|
69
|
+
store: {
|
70
|
+
model: {
|
71
|
+
fields: [
|
72
|
+
{name: 'id', type: 'Number'},
|
73
|
+
{name: 'name', type: 'String'}
|
74
|
+
]
|
75
|
+
},
|
76
|
+
data: [
|
77
|
+
{id: 1, name: 'Item 1'},
|
78
|
+
{id: 2, name: 'Item 2'}
|
79
|
+
]
|
80
|
+
}
|
81
|
+
```
|
82
|
+
|
83
|
+
### 2. Store Class Reference
|
84
|
+
|
85
|
+
For more complex data handling or reusable store logic, you can define a separate `Neo.data.Store` class and provide a
|
86
|
+
reference to it. The grid will then instantiate this class.
|
87
|
+
|
88
|
+
```javascript readonly
|
89
|
+
import MyCustomStore from './MyCustomStore.mjs'; // Assuming MyCustomStore extends Neo.data.Store
|
90
|
+
|
91
|
+
// ...
|
92
|
+
store: MyCustomStore
|
93
|
+
```
|
94
|
+
|
95
|
+
### 3. Pre-created Store Instance
|
96
|
+
|
97
|
+
If you need to share a single store instance across multiple grids or manage its lifecycle externally, you can create
|
98
|
+
the store instance beforehand and pass it directly to the grid.
|
99
|
+
|
100
|
+
```javascript readonly
|
101
|
+
import Store from '../data/Store.mjs';
|
102
|
+
|
103
|
+
const mySharedStore = Neo.create(Store, {
|
104
|
+
model: { /* ... */ },
|
105
|
+
data: [ /* ... */ ]
|
106
|
+
});
|
107
|
+
|
108
|
+
// ...
|
109
|
+
store: mySharedStore
|
110
|
+
```
|
111
|
+
|
112
|
+
Regardless of the method chosen, the grid's `beforeSetStore` hook (as seen in `Neo.grid.Container.mjs`) ensures that the
|
113
|
+
`store` property always resolves to a valid `Neo.data.Store` instance, providing a consistent and robust API.
|
114
|
+
|
115
|
+
### 4. Centralized Store Management with `Neo.state.Provider`
|
116
|
+
|
117
|
+
For more complex applications, `Neo.state.Provider` offers a powerful way to manage multiple stores centrally and share
|
118
|
+
them across various components using the binding system. This approach promotes better organization and reusability of
|
119
|
+
your data.
|
120
|
+
|
121
|
+
First, define your stores within a `Neo.state.Provider`'s `stores` config:
|
122
|
+
|
123
|
+
```javascript readonly
|
124
|
+
import Provider from '../state/Provider.mjs';
|
125
|
+
import Store from '../data/Store.mjs';
|
126
|
+
|
127
|
+
class AppStateProvider extends Provider {
|
128
|
+
static config = {
|
129
|
+
className: 'AppStateProvider',
|
130
|
+
stores: {
|
131
|
+
users: {
|
132
|
+
module: Store,
|
133
|
+
model : {fields: ['id', 'name']},
|
134
|
+
data : [{id: 1, name: 'Alice'}, {id: 2, name: 'Bob'}]
|
135
|
+
},
|
136
|
+
products: {
|
137
|
+
module: Store,
|
138
|
+
model : {fields: ['id', 'item', 'price']},
|
139
|
+
data : [{id: 1, item: 'Laptop', price: 1200}, {id: 2, item: 'Mouse', price: 25}]
|
140
|
+
}
|
141
|
+
}
|
142
|
+
}
|
143
|
+
}
|
144
|
+
Neo.setupClass(AppStateProvider);
|
145
|
+
```
|
146
|
+
|
147
|
+
Then, in your `GridContainer` (or any other component), you can bind to these stores using the `bind` config. The
|
148
|
+
`Neo.state.Provider` will automatically inject the correct store instance.
|
149
|
+
|
150
|
+
```javascript live-preview
|
151
|
+
import GridContainer from '../grid/Container.mjs';
|
152
|
+
import Provider from '../state/Provider.mjs';
|
153
|
+
import Store from '../data/Store.mjs';
|
154
|
+
import Viewport from '../container/Viewport.mjs';
|
155
|
+
|
156
|
+
class AppStateProvider extends Provider {
|
157
|
+
static config = {
|
158
|
+
className: 'AppStateProvider',
|
159
|
+
stores: {
|
160
|
+
users: {
|
161
|
+
module: Store,
|
162
|
+
model : { fields: ['id', 'name'] },
|
163
|
+
data : [{id: 1, name: 'Alice'}, {id: 2, name: 'Bob'}]
|
164
|
+
}
|
165
|
+
}
|
166
|
+
}
|
167
|
+
}
|
168
|
+
Neo.setupClass(AppStateProvider);
|
169
|
+
|
170
|
+
class MainView extends Viewport {
|
171
|
+
static config = {
|
172
|
+
className: 'MainView',
|
173
|
+
layout : {ntype: 'fit'},
|
174
|
+
// Attach the state provider to the viewport
|
175
|
+
stateProvider: AppStateProvider,
|
176
|
+
items : [{
|
177
|
+
module: GridContainer,
|
178
|
+
// Bind the grid's store config to the 'users' store defined in the state provider
|
179
|
+
bind: {
|
180
|
+
store: 'stores.users'
|
181
|
+
},
|
182
|
+
columns: [
|
183
|
+
{text: 'ID', dataField: 'id'},
|
184
|
+
{text: 'Name', dataField: 'name'}
|
185
|
+
]
|
186
|
+
}]
|
187
|
+
}
|
188
|
+
}
|
189
|
+
MainView = Neo.setupClass(MainView);
|
190
|
+
```
|
191
|
+
|
192
|
+
This pattern is particularly beneficial for:
|
193
|
+
* **Centralized State:** All application-level stores are defined in one place, making them easy to locate and manage.
|
194
|
+
* **Reusability:** Stores can be easily shared and reused across different parts of your application without manual
|
195
|
+
* instantiation and passing.
|
196
|
+
* **Decoupling:** Components become more decoupled from direct store instantiation, relying instead on the state provider
|
197
|
+
to inject the necessary data.
|
198
|
+
* **Testability:** Centralized stores can be more easily mocked or swapped for testing purposes.
|
199
|
+
|
200
|
+
## Columns
|
201
|
+
|
202
|
+
## Sorting
|
203
|
+
|
204
|
+
Neo.mjs grids provide built-in support for sorting data by one or more columns. Sorting is primarily managed by the
|
205
|
+
grid's underlying `Neo.data.Store`.
|
206
|
+
|
207
|
+
### Enabling Sorting
|
208
|
+
|
209
|
+
To enable sorting for a column, ensure the `sortable` config is set to `true` on the `Neo.grid.Container` (which is its
|
210
|
+
default value). Then, simply click on a column header to sort the data by that column. Clicking again will reverse the
|
211
|
+
sort direction.
|
212
|
+
|
213
|
+
```javascript live-preview
|
214
|
+
import GridContainer from '../grid/Container.mjs';
|
215
|
+
import Store from '../data/Store.mjs';
|
216
|
+
import Viewport from '../container/Viewport.mjs';
|
217
|
+
|
218
|
+
class MainView extends Viewport {
|
219
|
+
static config = {
|
220
|
+
className: 'MainView',
|
221
|
+
layout : {ntype: 'fit'},
|
222
|
+
items : [{
|
223
|
+
module: GridContainer,
|
224
|
+
sortable: true, // Default is true, but explicitly shown here
|
225
|
+
store : {
|
226
|
+
model: {
|
227
|
+
fields: [
|
228
|
+
{name: 'name', type: 'String'},
|
229
|
+
{name: 'age', type: 'Number'}
|
230
|
+
]
|
231
|
+
},
|
232
|
+
data: [
|
233
|
+
{name: 'Alice', age: 30},
|
234
|
+
{name: 'Bob', age: 24},
|
235
|
+
{name: 'Charlie', age: 35},
|
236
|
+
{name: 'David', age: 28}
|
237
|
+
]
|
238
|
+
},
|
239
|
+
columns: [
|
240
|
+
{text: 'Name', dataField: 'name'},
|
241
|
+
{text: 'Age', dataField: 'age'}
|
242
|
+
]
|
243
|
+
}]
|
244
|
+
}
|
245
|
+
}
|
246
|
+
MainView = Neo.setupClass(MainView);
|
247
|
+
```
|
248
|
+
|
249
|
+
### Initial Sorting
|
250
|
+
|
251
|
+
You can define an initial sort order for your store using the `sorters` config.
|
252
|
+
|
253
|
+
```javascript readonly
|
254
|
+
store: {
|
255
|
+
model: { /* ... */ },
|
256
|
+
data: [ /* ... */ ],
|
257
|
+
sorters: [{
|
258
|
+
property : 'name',
|
259
|
+
direction: 'ASC' // 'ASC' for ascending, 'DESC' for descending
|
260
|
+
}]
|
261
|
+
}
|
262
|
+
```
|
263
|
+
|
264
|
+
### Programmatic Sorting
|
265
|
+
|
266
|
+
You can also sort the store programmatically using the `sort` method of the store instance.
|
267
|
+
|
268
|
+
```javascript readonly
|
269
|
+
myGrid.getStore().sort({
|
270
|
+
property : 'age',
|
271
|
+
direction: 'DESC'
|
272
|
+
});
|
273
|
+
```
|
274
|
+
|
275
|
+
## Columns
|
276
|
+
|
277
|
+
Columns are the building blocks of a grid. You can configure them with various options.
|
278
|
+
|
279
|
+
### Column Types
|
280
|
+
|
281
|
+
Neo.mjs provides several specialized column types:
|
282
|
+
|
283
|
+
- `Neo.grid.column.Base`: The default column type.
|
284
|
+
- `Neo.grid.column.Index`: Displays the row number.
|
285
|
+
- `Neo.grid.column.Component`: Renders a Neo.mjs component inside each cell.
|
286
|
+
- `Neo.grid.column.Currency`: For formatting currency values.
|
287
|
+
- `Neo.grid.column.AnimatedChange`: Animates cell value changes.
|
288
|
+
- `Neo.grid.column.AnimatedCurrency`: Animates currency cell value changes.
|
289
|
+
- `Neo.grid.column.Progress`: Renders a progress bar component.
|
290
|
+
|
291
|
+
You can specify the column type using the `type` config:
|
292
|
+
|
293
|
+
```javascript readonly
|
294
|
+
{
|
295
|
+
type: 'index',
|
296
|
+
text: '#'
|
297
|
+
}
|
298
|
+
```
|
299
|
+
|
300
|
+
### Custom Rendering
|
301
|
+
|
302
|
+
For more complex cell content, you can use a `renderer` function. The renderer receives an object with details
|
303
|
+
about the cell, record, and store.
|
304
|
+
|
305
|
+
```javascript readonly
|
306
|
+
{
|
307
|
+
text : 'Full Name',
|
308
|
+
renderer: data => `${data.record.firstname} ${data.record.lastname}`
|
309
|
+
}
|
310
|
+
```
|
311
|
+
|
312
|
+
### Nested Record Fields
|
313
|
+
|
314
|
+
The grid supports displaying data from nested objects within your records. Simply use a dot-separated path for the
|
315
|
+
`dataField` config.
|
316
|
+
|
317
|
+
Given a record like:
|
318
|
+
```json
|
319
|
+
{
|
320
|
+
"id": 1,
|
321
|
+
"user": {
|
322
|
+
"firstname": "John",
|
323
|
+
"lastname" : "Doe"
|
324
|
+
}
|
325
|
+
}
|
326
|
+
```
|
327
|
+
|
328
|
+
You can define your columns like this:
|
329
|
+
```javascript readonly
|
330
|
+
columns: [
|
331
|
+
{text: 'Firstname', dataField: 'user.firstname'},
|
332
|
+
{text: 'Lastname', dataField: 'user.lastname'}
|
333
|
+
]
|
334
|
+
```
|
335
|
+
The `examples/grid/nestedRecordFields` example provides a live demonstration of this feature.
|
336
|
+
|
337
|
+
### Header Filters
|
338
|
+
|
339
|
+
Grids can include header filters, allowing users to filter data directly from the column headers. To enable this feature,
|
340
|
+
set the `showHeaderFilters` config to `true` on the `Neo.grid.Container`.
|
341
|
+
|
342
|
+
```javascript live-preview
|
343
|
+
import GridContainer from '../grid/Container.mjs';
|
344
|
+
import Store from '../data/Store.mjs';
|
345
|
+
import Viewport from '../container/Viewport.mjs';
|
346
|
+
|
347
|
+
class MainView extends Viewport {
|
348
|
+
static config = {
|
349
|
+
className: 'MainView',
|
350
|
+
layout : {ntype: 'fit'},
|
351
|
+
items : [{
|
352
|
+
module : GridContainer,
|
353
|
+
showHeaderFilters: true, // Enable header filters
|
354
|
+
store : {
|
355
|
+
model: {
|
356
|
+
fields: [
|
357
|
+
{name: 'city', type: 'String'},
|
358
|
+
{name: 'population', type: 'Number'}
|
359
|
+
]
|
360
|
+
},
|
361
|
+
data: [
|
362
|
+
{city: 'New York', population: 8419000},
|
363
|
+
{city: 'Los Angeles', population: 3980000},
|
364
|
+
{city: 'Chicago', population: 2716000},
|
365
|
+
{city: 'Houston', population: 2320000}
|
366
|
+
]
|
367
|
+
},
|
368
|
+
columns: [
|
369
|
+
{text: 'City', dataField: 'city', filterable: true},
|
370
|
+
{text: 'Population', dataField: 'population', filterable: true}
|
371
|
+
]
|
372
|
+
}]
|
373
|
+
}
|
374
|
+
}
|
375
|
+
MainView = Neo.setupClass(MainView);
|
376
|
+
```
|
377
|
+
|
378
|
+
For a column to be filterable, you must also set its `filterable` config to `true`. The grid automatically provides a
|
379
|
+
text input filter for string fields and a number input filter for number fields. More complex filter types can be
|
380
|
+
implemented by extending `Neo.grid.header.Filter`.
|
381
|
+
|
382
|
+
## Sorting
|
383
|
+
|
384
|
+
Neo.mjs grids provide built-in support for sorting data by one or more columns. Sorting is primarily managed by the
|
385
|
+
grid's underlying `Neo.data.Store`.
|
386
|
+
|
387
|
+
### Enabling Sorting
|
388
|
+
|
389
|
+
To enable sorting for a column, ensure the `sortable` config is set to `true` on the `Neo.grid.Container` (which is its
|
390
|
+
default value). Then, simply click on a column header to sort the data by that column. Clicking again will reverse the
|
391
|
+
sort direction.
|
392
|
+
|
393
|
+
```javascript live-preview
|
394
|
+
import GridContainer from '../grid/Container.mjs';
|
395
|
+
import Store from '../data/Store.mjs';
|
396
|
+
import Viewport from '../container/Viewport.mjs';
|
397
|
+
|
398
|
+
class MainView extends Viewport {
|
399
|
+
static config = {
|
400
|
+
className: 'MainView',
|
401
|
+
layout : {ntype: 'fit'},
|
402
|
+
items : [{
|
403
|
+
module: GridContainer,
|
404
|
+
sortable: true, // Default is true, but explicitly shown here
|
405
|
+
store : {
|
406
|
+
model: {
|
407
|
+
fields: [
|
408
|
+
{name: 'name', type: 'String'},
|
409
|
+
{name: 'age', type: 'Number'}
|
410
|
+
]
|
411
|
+
},
|
412
|
+
data: [
|
413
|
+
{name: 'Alice', age: 30},
|
414
|
+
{name: 'Bob', age: 24},
|
415
|
+
{name: 'Charlie', age: 35},
|
416
|
+
{name: 'David', age: 28}
|
417
|
+
]
|
418
|
+
},
|
419
|
+
columns: [
|
420
|
+
{text: 'Name', dataField: 'name'},
|
421
|
+
{text: 'Age', dataField: 'age'}
|
422
|
+
]
|
423
|
+
}]
|
424
|
+
}
|
425
|
+
}
|
426
|
+
MainView = Neo.setupClass(MainView);
|
427
|
+
```
|
428
|
+
|
429
|
+
### Initial Sorting
|
430
|
+
|
431
|
+
You can define an initial sort order for your store using the `sorters` config.
|
432
|
+
|
433
|
+
```javascript readonly
|
434
|
+
store: {
|
435
|
+
model: { /* ... */ },
|
436
|
+
data: [ /* ... */ ],
|
437
|
+
sorters: [{
|
438
|
+
property : 'name',
|
439
|
+
direction: 'ASC' // 'ASC' for ascending, 'DESC' for descending
|
440
|
+
}]
|
441
|
+
}
|
442
|
+
```
|
443
|
+
|
444
|
+
### Programmatic Sorting
|
445
|
+
|
446
|
+
You can also sort the store programmatically using one of the following 2 options:
|
447
|
+
|
448
|
+
```javascript readonly
|
449
|
+
// Option 1: Directly modifying the existing sorter
|
450
|
+
myGrid.getSorter('name').direction = 'DESC';
|
451
|
+
|
452
|
+
// Option 2: Assigning a new value to the sorters config
|
453
|
+
myGrid.sorters = [{
|
454
|
+
property : 'name',
|
455
|
+
direction: 'DESC'
|
456
|
+
}];
|
457
|
+
```
|
458
|
+
|
459
|
+
## Filtering
|
460
|
+
|
461
|
+
Beyond header filters, you can programmatically filter the grid's data using the `filters` config on the store.
|
462
|
+
This allows for more complex filtering logic and dynamic updates.
|
463
|
+
|
464
|
+
### Applying Filters
|
465
|
+
|
466
|
+
To apply filters, set the `filters` config on your store. This config accepts an array of filter objects.
|
467
|
+
|
468
|
+
```javascript live-preview
|
469
|
+
import GridContainer from '../grid/Container.mjs';
|
470
|
+
import Store from '../data/Store.mjs';
|
471
|
+
import Viewport from '../container/Viewport.mjs';
|
472
|
+
|
473
|
+
class MainView extends Viewport {
|
474
|
+
static config = {
|
475
|
+
className: 'MainView',
|
476
|
+
layout : {ntype: 'fit'},
|
477
|
+
items : [{
|
478
|
+
module: GridContainer,
|
479
|
+
store : {
|
480
|
+
model: {
|
481
|
+
fields: [
|
482
|
+
{name: 'product', type: 'String'},
|
483
|
+
{name: 'price', type: 'Number'}
|
484
|
+
]
|
485
|
+
},
|
486
|
+
data: [
|
487
|
+
{product: 'Laptop', price: 1200},
|
488
|
+
{product: 'Mouse', price: 25},
|
489
|
+
{product: 'Keyboard', price: 75},
|
490
|
+
{product: 'Monitor', price: 300}
|
491
|
+
],
|
492
|
+
filters: [{
|
493
|
+
property: 'price',
|
494
|
+
operator: '>=',
|
495
|
+
value : 100
|
496
|
+
}] // Initial filter: price >= 100
|
497
|
+
},
|
498
|
+
columns: [
|
499
|
+
{text: 'Product', dataField: 'product'},
|
500
|
+
{text: 'Price', dataField: 'price'}
|
501
|
+
]
|
502
|
+
}]
|
503
|
+
}
|
504
|
+
}
|
505
|
+
MainView = Neo.setupClass(MainView);
|
506
|
+
```
|
507
|
+
|
508
|
+
Each filter object typically has:
|
509
|
+
- `property`: The data field to filter on.
|
510
|
+
- `operator`: The comparison operator (e.g., `'='`, `'>'`, `'<='`, `'like'`).
|
511
|
+
- `value`: The value to compare against.
|
512
|
+
|
513
|
+
### Clearing Filters
|
514
|
+
|
515
|
+
To clear all filters, simply set the `filters` config to `null` or an empty array.
|
516
|
+
|
517
|
+
```javascript readonly
|
518
|
+
myGrid.getStore().filters = null;
|
519
|
+
// or
|
520
|
+
myGrid.getStore().filters = [];
|
521
|
+
```
|
522
|
+
|
523
|
+
### Adding Filters Programmatically
|
524
|
+
|
525
|
+
You can dynamically add or modify filters by getting the current filters, adding new ones, and then setting the `filters`
|
526
|
+
config again.
|
527
|
+
|
528
|
+
```javascript readonly
|
529
|
+
const store = myGrid.getStore();
|
530
|
+
const currentFilters = store.filters ? [...store.filters] : [];
|
531
|
+
|
532
|
+
currentFilters.push({
|
533
|
+
property: 'product',
|
534
|
+
operator: 'like',
|
535
|
+
value : 'o' // Filter products containing 'o'
|
536
|
+
});
|
537
|
+
|
538
|
+
store.filters = currentFilters;
|
539
|
+
```
|
540
|
+
|
541
|
+
## Plugins
|
542
|
+
|
543
|
+
Neo.mjs grids support various plugins to extend their functionality. Plugins are typically enabled by setting a
|
544
|
+
configuration property on the `Neo.grid.Container` or `Neo.grid.Body`.
|
545
|
+
|
546
|
+
### Cell Editing
|
547
|
+
|
548
|
+
Enable cell editing by setting the `cellEditing` config to `true` on the `Neo.grid.Container`.
|
549
|
+
|
550
|
+
```javascript readonly
|
551
|
+
const myGrid = Neo.create(GridContainer, {
|
552
|
+
cellEditing: true,
|
553
|
+
// ...
|
554
|
+
});
|
555
|
+
```
|
556
|
+
|
557
|
+
### Animated Row Sorting
|
558
|
+
|
559
|
+
To animate row sorting, set the `animatedRowSorting` config to `true` on the `Neo.grid.Body` (via `bodyConfig`).
|
560
|
+
|
561
|
+
```javascript readonly
|
562
|
+
const myGrid = Neo.create(GridContainer, {
|
563
|
+
bodyConfig: {
|
564
|
+
animatedRowSorting: true
|
565
|
+
},
|
566
|
+
// ...
|
567
|
+
});
|
568
|
+
```
|
569
|
+
|
570
|
+
## Selection Models
|
571
|
+
|
572
|
+
The grid's selection behavior is controlled by a selection model, which you can configure on the `bodyConfig`.
|
573
|
+
|
574
|
+
Available selection models in `Neo.selection.grid`:
|
575
|
+
- `RowModel`: Selects entire rows.
|
576
|
+
- `CellModel`: Selects individual cells.
|
577
|
+
- `ColumnModel`: Selects entire columns.
|
578
|
+
- And combinations like `CellRowModel`, `CellColumnModel`, `CellColumnRowModel`.
|
579
|
+
|
580
|
+
```javascript readonly
|
581
|
+
import {RowModel} from '../../../src/selection/grid/_export.mjs';
|
582
|
+
|
583
|
+
const myGrid = Neo.create(GridContainer, {
|
584
|
+
// ...
|
585
|
+
bodyConfig: {
|
586
|
+
selectionModel: RowModel
|
587
|
+
}
|
588
|
+
});
|
589
|
+
```
|
590
|
+
|
591
|
+
## Performance and Big Data
|
592
|
+
|
593
|
+
The grid is designed for exceptional performance, especially when dealing with large datasets. Its virtual rendering
|
594
|
+
engine ensures that only the visible parts of the grid (rows and columns) are rendered in the DOM, significantly
|
595
|
+
reducing memory consumption and improving rendering speed.
|
596
|
+
|
597
|
+
You### Optimizing Virtual Rendering
|
598
|
+
|
599
|
+
You can fine-tune the virtual rendering behavior with the `bufferRowRange` and `bufferColumnRange` configs in the
|
600
|
+
`bodyConfig`. These settings define how many extra rows and columns to render outside the visible area to provide a
|
601
|
+
smoother scrolling experience.
|
602
|
+
|
603
|
+
```javascript readonly
|
604
|
+
const myGrid = Neo.create(GridContainer, {
|
605
|
+
bodyConfig: {
|
606
|
+
bufferRowRange : 5, // Render 5 extra rows above and below the visible area
|
607
|
+
bufferColumnRange: 2 // Render 2 extra columns to the left and right of the visible area
|
608
|
+
},
|
609
|
+
// ...
|
610
|
+
});
|
611
|
+
```
|
612
|
+
|
613
|
+
### Row Height
|
614
|
+
|
615
|
+
The `rowHeight` config on the `Neo.grid.Container` plays a crucial role in the grid's rendering calculations. Ensuring
|
616
|
+
an accurate `rowHeight` is essential for the virtual rendering engine to correctly determine the number of visible rows
|
617
|
+
and the scrollable area. While the default value of `32px` is often suitable, you should adjust it if your grid rows
|
618
|
+
have a different fixed height.
|
619
|
+
|
620
|
+
The `examples/grid/bigData` example showcases the grid's performance with a large dataset, allowing you to
|
621
|
+
dynamically adjust the number of rows and columns.
|