@ea-lab/reactive-json-docs 1.4.1 → 2.0.1
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/package.json +2 -2
- package/public/rjbuild/docs/core/attributeTransformer/setAttributeValue.md +14 -117
- package/public/rjbuild/docs/core/attributeTransformer/setAttributeValue.yaml +12 -144
- package/public/rjbuild/docs/core/element/special/DataSync.md +252 -0
- package/public/rjbuild/docs/core/element/special/DataSync.yaml +274 -0
- package/public/rjbuild/docs/core/example/DataFilter-example-direct-array.md +0 -211
- package/public/rjbuild/docs/core/example/DataFilter-example-direct-array.yaml +0 -323
- package/public/rjbuild/docs/core/example/button-wrapper-pattern.md +0 -99
- package/public/rjbuild/docs/core/example/button-wrapper-pattern.yaml +0 -132
- package/public/rjbuild/docs/core/example/conditional-field-with-dual-update.md +0 -209
- package/public/rjbuild/docs/core/example/conditional-field-with-dual-update.yaml +0 -74
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
renderView:
|
|
2
|
+
- type: Markdown
|
|
3
|
+
content: |
|
|
4
|
+
# DataSync
|
|
5
|
+
|
|
6
|
+
The `DataSync` component enables automatic synchronization between client-side data and a backend endpoint. It watches a **Syncable Object** in the data tree and pushes changes to a server, either automatically after a period of inactivity, immediately on change, or manually via an explicit trigger.
|
|
7
|
+
|
|
8
|
+
This component does not render any visible UI. It acts as a background observer.
|
|
9
|
+
|
|
10
|
+
## The Syncable Object
|
|
11
|
+
|
|
12
|
+
`DataSync` watches a data object that follows a specific structure called a **Syncable Object**. This object contains both the data to synchronize and the configuration needed to reach the backend.
|
|
13
|
+
|
|
14
|
+
### Structure
|
|
15
|
+
|
|
16
|
+
```yaml
|
|
17
|
+
mySyncableObject:
|
|
18
|
+
submission_url: "https://api.example.com/items/save"
|
|
19
|
+
item_url: "https://api.example.com/items/123"
|
|
20
|
+
delete_url: "https://api.example.com/items/123"
|
|
21
|
+
data:
|
|
22
|
+
entity_id: 123
|
|
23
|
+
name: "John Doe"
|
|
24
|
+
email: "john@example.com"
|
|
25
|
+
status:
|
|
26
|
+
type: "info"
|
|
27
|
+
message: "Ready"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Syncable Object Fields
|
|
31
|
+
|
|
32
|
+
- type: DefinitionList
|
|
33
|
+
content:
|
|
34
|
+
- term:
|
|
35
|
+
code: submission_url
|
|
36
|
+
after: " (string, required)"
|
|
37
|
+
details:
|
|
38
|
+
type: Markdown
|
|
39
|
+
content: "URL where the object is sent for create/update (POST). This is the only URL used by the `DataSync` component. If `entity_id` is absent from `data`, the backend should treat it as a creation."
|
|
40
|
+
- term:
|
|
41
|
+
code: item_url
|
|
42
|
+
after: " (string, optional)"
|
|
43
|
+
details:
|
|
44
|
+
type: Markdown
|
|
45
|
+
content: "URL to fetch the latest version of the item (GET). **Not used by `DataSync` itself** — provided as metadata for the backend or other components."
|
|
46
|
+
- term:
|
|
47
|
+
code: delete_url
|
|
48
|
+
after: " (string, optional)"
|
|
49
|
+
details:
|
|
50
|
+
type: Markdown
|
|
51
|
+
content: "URL to delete the item (DELETE). **Not used by `DataSync` itself** — provided as metadata for the backend or other components."
|
|
52
|
+
- term:
|
|
53
|
+
code: data
|
|
54
|
+
after: " (any, required)"
|
|
55
|
+
details:
|
|
56
|
+
type: Markdown
|
|
57
|
+
content: "The actual payload to synchronize. Its structure depends on the backend. **Only changes to this field trigger synchronization.**"
|
|
58
|
+
- term:
|
|
59
|
+
code: status
|
|
60
|
+
after: " (object, optional)"
|
|
61
|
+
details:
|
|
62
|
+
- type: Markdown
|
|
63
|
+
content: "Feedback message from the last operation. Contains:"
|
|
64
|
+
- type: DefinitionList
|
|
65
|
+
content:
|
|
66
|
+
- term:
|
|
67
|
+
code: status.type
|
|
68
|
+
details:
|
|
69
|
+
type: Markdown
|
|
70
|
+
content: "One of: `success`, `error`, `info`, `warning`."
|
|
71
|
+
- term:
|
|
72
|
+
code: status.message
|
|
73
|
+
details: "Human-readable message describing the result."
|
|
74
|
+
|
|
75
|
+
- type: Markdown
|
|
76
|
+
content: |
|
|
77
|
+
### How `status` is managed
|
|
78
|
+
|
|
79
|
+
1. **By the component**: Set to `{ type: "info", message: "Synchronisation en cours..." }` while a request is in flight.
|
|
80
|
+
2. **By the backend**: The server response replaces the entire Syncable Object, including the `status` field. The backend can set it to any type with a relevant message.
|
|
81
|
+
3. **On HTTP failure**: If the request fails (network error, 5xx), the component generates `{ type: "error", message: "..." }` locally.
|
|
82
|
+
|
|
83
|
+
### Backend contract
|
|
84
|
+
|
|
85
|
+
When `DataSync` sends a request, it POSTs the **entire Syncable Object** (not just `data`) to `submission_url`. The backend must return the same Syncable Object structure in its response, potentially with:
|
|
86
|
+
- Modified `data` (e.g., server-generated fields like `entity_id` or timestamps).
|
|
87
|
+
- An updated `status` field reflecting the result of the operation.
|
|
88
|
+
|
|
89
|
+
The response completely replaces the local Syncable Object.
|
|
90
|
+
|
|
91
|
+
## Component Properties
|
|
92
|
+
|
|
93
|
+
- type: TabbedSerializer
|
|
94
|
+
yamlSerializedContent: |
|
|
95
|
+
- type: DataSync
|
|
96
|
+
path: ~~.mySyncableObject
|
|
97
|
+
mode: onIdle
|
|
98
|
+
idleDelay: 2000
|
|
99
|
+
trigger: ~~.saveNow
|
|
100
|
+
maxRetries: 0
|
|
101
|
+
retryDelay: 5000
|
|
102
|
+
|
|
103
|
+
- type: DefinitionList
|
|
104
|
+
content:
|
|
105
|
+
- term:
|
|
106
|
+
code: path
|
|
107
|
+
after: " (string, required)"
|
|
108
|
+
details:
|
|
109
|
+
type: Markdown
|
|
110
|
+
content: "Path to the Syncable Object to watch. Supports template paths (`~~.`, `~.`, `~>`)."
|
|
111
|
+
- term:
|
|
112
|
+
code: mode
|
|
113
|
+
after: " (string, optional)"
|
|
114
|
+
details:
|
|
115
|
+
type: Markdown
|
|
116
|
+
content: "Synchronization mode. Default: `\"onIdle\"`. Options: `\"onIdle\"`, `\"immediate\"`, `\"manual\"`."
|
|
117
|
+
- term:
|
|
118
|
+
code: idleDelay
|
|
119
|
+
after: " (number, optional)"
|
|
120
|
+
details:
|
|
121
|
+
type: Markdown
|
|
122
|
+
content: "Milliseconds of inactivity before syncing. Only used in `onIdle` mode. Default: `1000`."
|
|
123
|
+
- term:
|
|
124
|
+
code: trigger
|
|
125
|
+
after: " (string, optional)"
|
|
126
|
+
details:
|
|
127
|
+
type: Markdown
|
|
128
|
+
content: "Path to a boolean value. When set to `true`, triggers an immediate sync and resets to `false`. Works in **any mode**. In `onIdle` mode, it cancels the pending idle timer."
|
|
129
|
+
- term:
|
|
130
|
+
code: maxRetries
|
|
131
|
+
after: " (number, optional)"
|
|
132
|
+
details:
|
|
133
|
+
type: Markdown
|
|
134
|
+
content: "Number of additional retry attempts after a failed sync. `0` means one attempt with no retry. Default: `0`."
|
|
135
|
+
- term:
|
|
136
|
+
code: retryDelay
|
|
137
|
+
after: " (number, optional)"
|
|
138
|
+
details:
|
|
139
|
+
type: Markdown
|
|
140
|
+
content: "Milliseconds between retry attempts. Default: `5000`."
|
|
141
|
+
|
|
142
|
+
- type: Markdown
|
|
143
|
+
content: |
|
|
144
|
+
## Synchronization Modes
|
|
145
|
+
|
|
146
|
+
### `onIdle` (default)
|
|
147
|
+
Waits for the user to stop modifying data. Each change resets the idle timer. The sync fires only after `idleDelay` milliseconds of inactivity.
|
|
148
|
+
|
|
149
|
+
```yaml
|
|
150
|
+
- type: DataSync
|
|
151
|
+
path: ~~.userProfile
|
|
152
|
+
mode: onIdle
|
|
153
|
+
idleDelay: 2000
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### `immediate`
|
|
157
|
+
Syncs immediately on every data change. Use with caution — this can generate a high volume of requests.
|
|
158
|
+
|
|
159
|
+
```yaml
|
|
160
|
+
- type: DataSync
|
|
161
|
+
path: ~~.settings
|
|
162
|
+
mode: immediate
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### `manual`
|
|
166
|
+
Does not sync on data changes. Waits for the `trigger` path to become `true`.
|
|
167
|
+
|
|
168
|
+
```yaml
|
|
169
|
+
- type: DataSync
|
|
170
|
+
path: ~~.formData
|
|
171
|
+
mode: manual
|
|
172
|
+
trigger: ~~.saveNow
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Manual Trigger
|
|
176
|
+
|
|
177
|
+
The `trigger` property works in **any mode**, not just `manual`. When the trigger path is set to `true`:
|
|
178
|
+
|
|
179
|
+
1. The trigger is immediately reset to `false`.
|
|
180
|
+
2. Any pending idle timer is cancelled (in `onIdle` mode).
|
|
181
|
+
3. A sync is performed immediately.
|
|
182
|
+
|
|
183
|
+
This is useful for adding a "Save Now" button alongside auto-save:
|
|
184
|
+
|
|
185
|
+
```yaml
|
|
186
|
+
- type: button
|
|
187
|
+
content: "Save Now"
|
|
188
|
+
actions:
|
|
189
|
+
- what: setData
|
|
190
|
+
on: click
|
|
191
|
+
path: ~~.saveNow
|
|
192
|
+
value: true
|
|
193
|
+
|
|
194
|
+
- type: DataSync
|
|
195
|
+
path: ~~.userProfile
|
|
196
|
+
mode: onIdle
|
|
197
|
+
idleDelay: 2000
|
|
198
|
+
trigger: ~~.saveNow
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Error Handling and Retries
|
|
202
|
+
|
|
203
|
+
### What triggers retries
|
|
204
|
+
- **Network outages** (browser is offline) — retried.
|
|
205
|
+
- **Server errors** (HTTP 5xx) — retried.
|
|
206
|
+
- **Client errors** (HTTP 4xx) — **not retried**.
|
|
207
|
+
- **CORS failures** — **not retried**.
|
|
208
|
+
|
|
209
|
+
When the user makes a new data change, the retry counter resets and a fresh sync cycle begins.
|
|
210
|
+
|
|
211
|
+
### Configuration example
|
|
212
|
+
```yaml
|
|
213
|
+
- type: DataSync
|
|
214
|
+
path: ~~.userProfile
|
|
215
|
+
mode: onIdle
|
|
216
|
+
idleDelay: 1000
|
|
217
|
+
maxRetries: 3
|
|
218
|
+
retryDelay: 10000
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Change Detection
|
|
222
|
+
|
|
223
|
+
`DataSync` only triggers synchronization when the `data` field of the Syncable Object changes. Changes to `status`, `submission_url`, or other fields are ignored. This prevents feedback loops when the component updates the status or when the server response updates the object.
|
|
224
|
+
|
|
225
|
+
## Using with Templates
|
|
226
|
+
|
|
227
|
+
`DataSync` supports `TemplateContext`, so it can be used inside templates to sync individual items in a list:
|
|
228
|
+
|
|
229
|
+
```yaml
|
|
230
|
+
data:
|
|
231
|
+
items:
|
|
232
|
+
- submission_url: "/api/items/1"
|
|
233
|
+
data: { name: "Item 1" }
|
|
234
|
+
- submission_url: "/api/items/2"
|
|
235
|
+
data: { name: "Item 2" }
|
|
236
|
+
|
|
237
|
+
templates:
|
|
238
|
+
itemRow:
|
|
239
|
+
type: div
|
|
240
|
+
content:
|
|
241
|
+
- type: TextField
|
|
242
|
+
dataLocation: ~.data.name
|
|
243
|
+
- type: DataSync
|
|
244
|
+
path: ~
|
|
245
|
+
mode: onIdle
|
|
246
|
+
idleDelay: 1500
|
|
247
|
+
|
|
248
|
+
renderView:
|
|
249
|
+
- type: Switch
|
|
250
|
+
content: ~~.items
|
|
251
|
+
singleOption:
|
|
252
|
+
load: itemRow
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Displaying Status
|
|
256
|
+
|
|
257
|
+
You can display the status message from the Syncable Object to provide user feedback:
|
|
258
|
+
|
|
259
|
+
```yaml
|
|
260
|
+
- type: div
|
|
261
|
+
content: ~~.userProfile.status.message
|
|
262
|
+
actions:
|
|
263
|
+
- what: hide
|
|
264
|
+
when: ~~.userProfile.status
|
|
265
|
+
is: undefined
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
## Limitations
|
|
269
|
+
- Only one sync can be active at a time per `DataSync` instance. Concurrent changes while a sync is in flight are not queued.
|
|
270
|
+
- The entire Syncable Object is sent in the POST body, not just the `data` field.
|
|
271
|
+
- Only POST requests are supported for submission. Custom HTTP methods are not configurable.
|
|
272
|
+
- `item_url` and `delete_url` are part of the Syncable Object structure but are not used by the component itself. They are available for the backend or for other components to use.
|
|
273
|
+
- No built-in support for optimistic updates. The local data is replaced by the server response.
|
|
274
|
+
- CORS errors are not retried (they are indistinguishable from network errors when the browser is online).
|
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
# DataFilter Example: Filtering Direct Array Items
|
|
2
|
-
|
|
3
|
-
This example demonstrates how to use `DataFilter` with arrays where each item is a direct object (not wrapped in a namespace property). This is useful when working with data from APIs that return arrays of objects directly.
|
|
4
|
-
|
|
5
|
-
## Use Case
|
|
6
|
-
|
|
7
|
-
When your data structure is a direct array of objects like:
|
|
8
|
-
```yaml
|
|
9
|
-
data:
|
|
10
|
-
rows:
|
|
11
|
-
- id: 1
|
|
12
|
-
label: "Operation 1"
|
|
13
|
-
done: "done"
|
|
14
|
-
operation: "create"
|
|
15
|
-
- id: 2
|
|
16
|
-
label: "Operation 2"
|
|
17
|
-
done: "pending"
|
|
18
|
-
operation: "update"
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
Instead of:
|
|
22
|
-
```yaml
|
|
23
|
-
data:
|
|
24
|
-
rows:
|
|
25
|
-
- item:
|
|
26
|
-
id: 1
|
|
27
|
-
label: "Operation 1"
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
## Solution
|
|
31
|
-
|
|
32
|
-
Use an existing property that is present in all items (like `id`) as the `subjectsWithProperty` namespace. In `whenFilterableData`, reference properties directly without the namespace prefix.
|
|
33
|
-
|
|
34
|
-
**Important**: When using string values for filtering (like status), use a special value like `"all"` to represent "no filter" instead of an empty string, as empty strings can cause issues with select elements.
|
|
35
|
-
|
|
36
|
-
## Complete Example
|
|
37
|
-
|
|
38
|
-
```yaml
|
|
39
|
-
renderView:
|
|
40
|
-
- type: DataFilter
|
|
41
|
-
context: global
|
|
42
|
-
filters:
|
|
43
|
-
- subjectsWithProperty: id
|
|
44
|
-
andConditions:
|
|
45
|
-
# Filter by status (string)
|
|
46
|
-
- orConditions:
|
|
47
|
-
- when: ~~._filters.done
|
|
48
|
-
is: "all"
|
|
49
|
-
- whenFilterableData: done
|
|
50
|
-
is: ~~._filters.done
|
|
51
|
-
|
|
52
|
-
# Filter by operation type (text search with contains)
|
|
53
|
-
- orConditions:
|
|
54
|
-
- when: ~~._filters.operation
|
|
55
|
-
is: ""
|
|
56
|
-
- andConditions:
|
|
57
|
-
- whenFilterableData: operation
|
|
58
|
-
isNotEmpty: true
|
|
59
|
-
- when: ~~._filters.operation
|
|
60
|
-
isNotEmpty: true
|
|
61
|
-
- whenFilterableData: operation
|
|
62
|
-
contains: ~~._filters.operation
|
|
63
|
-
|
|
64
|
-
# Filter by label (text search with contains)
|
|
65
|
-
- orConditions:
|
|
66
|
-
- when: ~~._filters.label
|
|
67
|
-
is: ""
|
|
68
|
-
- andConditions:
|
|
69
|
-
- whenFilterableData: label
|
|
70
|
-
isNotEmpty: true
|
|
71
|
-
- when: ~~._filters.label
|
|
72
|
-
isNotEmpty: true
|
|
73
|
-
- whenFilterableData: label
|
|
74
|
-
contains: ~~._filters.label
|
|
75
|
-
content:
|
|
76
|
-
- type: Switch
|
|
77
|
-
content: ~~.rows
|
|
78
|
-
singleOption:
|
|
79
|
-
load: operationRow
|
|
80
|
-
|
|
81
|
-
templates:
|
|
82
|
-
operationRow:
|
|
83
|
-
- type: tr
|
|
84
|
-
content:
|
|
85
|
-
- type: td
|
|
86
|
-
content: ~.id
|
|
87
|
-
- type: td
|
|
88
|
-
content: ~.label
|
|
89
|
-
- type: td
|
|
90
|
-
content: ~.done
|
|
91
|
-
- type: td
|
|
92
|
-
content: ~.operation
|
|
93
|
-
|
|
94
|
-
data:
|
|
95
|
-
rows:
|
|
96
|
-
- id: 1
|
|
97
|
-
label: "Operation 1"
|
|
98
|
-
done: "done"
|
|
99
|
-
operation: "create"
|
|
100
|
-
- id: 2
|
|
101
|
-
label: "Operation 2"
|
|
102
|
-
done: "pending"
|
|
103
|
-
operation: "update"
|
|
104
|
-
- id: 3
|
|
105
|
-
label: "Operation 3"
|
|
106
|
-
done: "done"
|
|
107
|
-
operation: "create"
|
|
108
|
-
_filters:
|
|
109
|
-
done: "all"
|
|
110
|
-
label: ""
|
|
111
|
-
operation: ""
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
## Key Points
|
|
115
|
-
|
|
116
|
-
1. **Namespace Selection**: Choose a property that exists in all items (e.g., `id`, `name`, `key`). This property acts as the identifier for DataFilter to recognize filterable items.
|
|
117
|
-
|
|
118
|
-
2. **Direct Property Access**: In `whenFilterableData`, reference properties directly:
|
|
119
|
-
- ✅ `whenFilterableData: label` (correct)
|
|
120
|
-
- ❌ `whenFilterableData: id.label` (incorrect - don't use namespace prefix)
|
|
121
|
-
|
|
122
|
-
3. **String-based Filtering**: When using select elements for filtering, use a special value like `"all"` to represent "no filter" instead of an empty string:
|
|
123
|
-
```yaml
|
|
124
|
-
- orConditions:
|
|
125
|
-
- when: ~~._filters.done
|
|
126
|
-
is: "all" # Shows all items
|
|
127
|
-
- whenFilterableData: done
|
|
128
|
-
is: ~~._filters.done # Filters by exact match
|
|
129
|
-
```
|
|
130
|
-
This avoids issues where select elements might not properly handle empty string values.
|
|
131
|
-
|
|
132
|
-
4. **Text Search**: For text search with `contains`, ensure both the filter value and the data property are not empty:
|
|
133
|
-
```yaml
|
|
134
|
-
- orConditions:
|
|
135
|
-
- when: ~~._filters.label
|
|
136
|
-
is: "" # Shows all when empty
|
|
137
|
-
- andConditions:
|
|
138
|
-
- whenFilterableData: label
|
|
139
|
-
isNotEmpty: true
|
|
140
|
-
- when: ~~._filters.label
|
|
141
|
-
isNotEmpty: true
|
|
142
|
-
- whenFilterableData: label
|
|
143
|
-
contains: ~~._filters.label
|
|
144
|
-
```
|
|
145
|
-
The `andConditions` wrapper ensures that both the data property and filter value are not empty before attempting the `contains` comparison.
|
|
146
|
-
|
|
147
|
-
5. **Template Access**: In templates, access properties directly without namespace:
|
|
148
|
-
- ✅ `~.label`, `~.done`, `~.operation`
|
|
149
|
-
- ❌ `~.id.label` (incorrect)
|
|
150
|
-
|
|
151
|
-
## Filter Types Demonstrated
|
|
152
|
-
|
|
153
|
-
- **Select Filter with "All" option**: Using `is: "all"` to show all items when a special "all" value is selected
|
|
154
|
-
- **Exact String Match**: Using `is` for exact string matching (e.g., status filtering)
|
|
155
|
-
- **Text Search**: Using `contains` for substring matching (case-insensitive) with proper empty checks
|
|
156
|
-
|
|
157
|
-
## Additional Template Techniques
|
|
158
|
-
|
|
159
|
-
**Conditional Display in Templates**: The example uses `hide` actions to conditionally display badges based on data values. This is a common pattern for showing different UI elements based on data state:
|
|
160
|
-
|
|
161
|
-
```yaml
|
|
162
|
-
- type: span
|
|
163
|
-
content: "Done"
|
|
164
|
-
actions:
|
|
165
|
-
- what: hide
|
|
166
|
-
when: ~.done
|
|
167
|
-
isNot: "done" # Hide if status is not "done"
|
|
168
|
-
- type: span
|
|
169
|
-
content: "Pending"
|
|
170
|
-
actions:
|
|
171
|
-
- what: hide
|
|
172
|
-
when: ~.done
|
|
173
|
-
isNot: "pending" # Hide if status is not "pending"
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
This technique is used in the example to display colored status badges, but it's not part of the DataFilter pattern itself - it's just a way to enhance the visual display of filtered data.
|
|
177
|
-
|
|
178
|
-
## Filter Patterns
|
|
179
|
-
|
|
180
|
-
### Pattern 1: Select Filter with "All" Option
|
|
181
|
-
```yaml
|
|
182
|
-
- orConditions:
|
|
183
|
-
- when: ~~._filters.status
|
|
184
|
-
is: "all" # Special value for "show all"
|
|
185
|
-
- whenFilterableData: status
|
|
186
|
-
is: ~~._filters.status # Exact match filter
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
### Pattern 2: Text Input Filter (Empty String Check)
|
|
190
|
-
```yaml
|
|
191
|
-
- orConditions:
|
|
192
|
-
- when: ~~._filters.search
|
|
193
|
-
is: "" # Empty string means "show all"
|
|
194
|
-
- andConditions:
|
|
195
|
-
- whenFilterableData: searchField
|
|
196
|
-
isNotEmpty: true
|
|
197
|
-
- when: ~~._filters.search
|
|
198
|
-
isNotEmpty: true
|
|
199
|
-
- whenFilterableData: searchField
|
|
200
|
-
contains: ~~._filters.search
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
## Notes
|
|
204
|
-
|
|
205
|
-
- The `subjectsWithProperty` value (`id` in this example) must exist in every item of the array
|
|
206
|
-
- DataFilter filters the data before rendering, so no `hide` actions are needed in templates
|
|
207
|
-
- All filter conditions use `orConditions` with an empty/"all" check first, allowing "show all" when filters are empty or set to "all"
|
|
208
|
-
- For select elements, prefer using a special value like `"all"` instead of empty strings to avoid UI issues
|
|
209
|
-
- For text inputs, empty strings (`""`) work fine for the "show all" condition
|
|
210
|
-
- When using `contains` for text search, always wrap the condition in `andConditions` with `isNotEmpty` checks to avoid errors with empty values
|
|
211
|
-
|