@ea-lab/reactive-json-docs 1.1.1 → 1.3.0
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/element/form/CheckBoxField.md +364 -0
- package/public/rjbuild/docs/core/element/form/CheckBoxField.yaml +222 -0
- package/public/rjbuild/docs/core/element/form/SelectField.md +384 -0
- package/public/rjbuild/docs/core/element/form/SelectField.yaml +252 -0
- package/public/rjbuild/docs/core/element/form/TextAreaField.md +297 -0
- package/public/rjbuild/docs/core/element/form/TextAreaField.yaml +139 -0
- package/public/rjbuild/docs/core/example/bulk-actions.md +405 -0
- package/public/rjbuild/docs/core/example/bulk-actions.yaml +514 -0
- package/public/rjbuild/docs/core/example/editable-modal-in-row.md +281 -0
- package/public/rjbuild/docs/core/example/editable-modal-in-row.yaml +415 -0
- package/public/rjbuild/docs/getting-started/rjbuild-structure.md +24 -0
- package/public/rjbuild/docs/getting-started/rjbuild-structure.yaml +26 -0
- package/public/rjbuild/docs/install.md +69 -20
- package/public/rjbuild/docs/install.yaml +141 -38
- /package/public/rjbuild/docs/{integration/bootstrap → core}/element/form/formElementsCommon.md +0 -0
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
# Bulk Actions System
|
|
2
|
+
|
|
3
|
+
This guide demonstrates how to implement a bulk action system that allows users to select multiple items in a list and perform actions on all selected items simultaneously. This pattern is commonly used in data tables, file managers, and admin interfaces.
|
|
4
|
+
|
|
5
|
+
## Core Concept
|
|
6
|
+
|
|
7
|
+
The bulk action system uses a combination of:
|
|
8
|
+
- **Selection state**: Track which items are selected using checkboxes
|
|
9
|
+
- **Data attributes**: Mark selected rows in the DOM for CSS selector targeting
|
|
10
|
+
- **Event delegation**: Use `triggerEvent` to programmatically trigger actions on multiple elements
|
|
11
|
+
- **Conditional actions**: Ensure actions only execute on selected items
|
|
12
|
+
|
|
13
|
+
## Concepts We Will Use
|
|
14
|
+
|
|
15
|
+
This pattern leverages several Reactive-JSON features:
|
|
16
|
+
|
|
17
|
+
- **[Switch Component](../element/special/Switch.md)**: Iterate over a collection of items and render each with a template
|
|
18
|
+
- **[SetAttributeValue Action](../action/Attribute/SetAttributeValue.md)**: Dynamically set HTML attributes (like `data-selected`) based on data state
|
|
19
|
+
- **[triggerEvent Reaction](../reaction/triggerEvent.md)**: Programmatically dispatch events on multiple elements matching a CSS selector
|
|
20
|
+
- **[Template Contexts](../getting-started/template-contexts-data-binding.md)**: Use `~.` for row-scoped data and `~~.` for global data
|
|
21
|
+
- **[Conditional Actions](../getting-started/actions.md)**: Use `when` conditions to control when actions execute
|
|
22
|
+
|
|
23
|
+
## Prerequisites
|
|
24
|
+
|
|
25
|
+
Before implementing bulk actions, you should understand:
|
|
26
|
+
|
|
27
|
+
1. **Template system**: How `Switch` renders items using templates
|
|
28
|
+
2. **Data binding**: The difference between `~.` (local template context) and `~~.` (global context)
|
|
29
|
+
3. **Actions and reactions**: How to define actions that respond to user interactions
|
|
30
|
+
4. **CSS selectors**: Basic understanding of attribute selectors like `[data-selected="true"]`
|
|
31
|
+
|
|
32
|
+
## Steps
|
|
33
|
+
|
|
34
|
+
### Step 1: Set Up Selection State
|
|
35
|
+
|
|
36
|
+
Add a `selected` property to each item in your data array and a global `bulkAction` variable:
|
|
37
|
+
|
|
38
|
+
```yaml
|
|
39
|
+
data:
|
|
40
|
+
items: []
|
|
41
|
+
bulkAction: ""
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Each item in the array should have a `selected` boolean property (can be initialized as `false` or added dynamically).
|
|
45
|
+
|
|
46
|
+
### Step 2: Add Selection Checkboxes
|
|
47
|
+
|
|
48
|
+
Add checkboxes to each row to allow users to select individual items:
|
|
49
|
+
|
|
50
|
+
```yaml
|
|
51
|
+
templates:
|
|
52
|
+
itemRow:
|
|
53
|
+
- type: tr
|
|
54
|
+
content:
|
|
55
|
+
- type: td
|
|
56
|
+
content:
|
|
57
|
+
- type: CheckBoxField
|
|
58
|
+
dataLocation: ~.selected
|
|
59
|
+
defaultFieldValue: false
|
|
60
|
+
options:
|
|
61
|
+
- label: ""
|
|
62
|
+
value: true
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Step 3: Mark Selected Rows with Data Attributes
|
|
66
|
+
|
|
67
|
+
Use `setAttributeValue` action to add a `data-selected` attribute to rows when they are selected. This allows CSS selectors to target selected rows:
|
|
68
|
+
|
|
69
|
+
```yaml
|
|
70
|
+
templates:
|
|
71
|
+
itemRow:
|
|
72
|
+
- type: tr
|
|
73
|
+
actions:
|
|
74
|
+
- what: setAttributeValue
|
|
75
|
+
name: "data-selected"
|
|
76
|
+
value: "true"
|
|
77
|
+
mode: "replace"
|
|
78
|
+
when: ~.selected
|
|
79
|
+
is: true
|
|
80
|
+
content:
|
|
81
|
+
# ... row content
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Important**: Use `mode: "replace"` to ensure the attribute is removed when `selected` becomes `false`. You may also want to add an action to remove the attribute when not selected.
|
|
85
|
+
|
|
86
|
+
### Step 4: Add Action Buttons with Data Attributes
|
|
87
|
+
|
|
88
|
+
Add `data-action` attributes to action buttons so they can be targeted by CSS selectors:
|
|
89
|
+
|
|
90
|
+
```yaml
|
|
91
|
+
- type: button
|
|
92
|
+
attributes:
|
|
93
|
+
data-action: "process"
|
|
94
|
+
type: "button"
|
|
95
|
+
content: "Process"
|
|
96
|
+
actions:
|
|
97
|
+
- what: submitData
|
|
98
|
+
on: click
|
|
99
|
+
# ... action configuration
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Step 5: Create Bulk Action Controls
|
|
103
|
+
|
|
104
|
+
Add a bulk action selector and execute button in your main view:
|
|
105
|
+
|
|
106
|
+
```yaml
|
|
107
|
+
renderView:
|
|
108
|
+
- type: SelectField
|
|
109
|
+
dataLocation: ~~.bulkAction
|
|
110
|
+
defaultFieldValue: ""
|
|
111
|
+
options:
|
|
112
|
+
- value: ""
|
|
113
|
+
label: "-- Choose action --"
|
|
114
|
+
- value: "process"
|
|
115
|
+
label: "Process selected items"
|
|
116
|
+
|
|
117
|
+
- type: button
|
|
118
|
+
content: "Execute"
|
|
119
|
+
actions:
|
|
120
|
+
- what: hide
|
|
121
|
+
when: ~~.bulkAction
|
|
122
|
+
isEmpty: true
|
|
123
|
+
- what: triggerEvent
|
|
124
|
+
on: click
|
|
125
|
+
eventName: "click"
|
|
126
|
+
selector: "tr[data-selected=\"true\"] button[data-action=\"process\"]"
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Step 6: Add Safety Conditions
|
|
130
|
+
|
|
131
|
+
Add conditions to prevent actions from executing on items that shouldn't be processed:
|
|
132
|
+
|
|
133
|
+
```yaml
|
|
134
|
+
- type: button
|
|
135
|
+
attributes:
|
|
136
|
+
data-action: "process"
|
|
137
|
+
actions:
|
|
138
|
+
- what: hide
|
|
139
|
+
when: ~.status
|
|
140
|
+
is: "processed" # Hide button if already processed
|
|
141
|
+
- what: submitData
|
|
142
|
+
on: click
|
|
143
|
+
# ... only executes if button is visible
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Complete Example
|
|
147
|
+
|
|
148
|
+
Here's a complete example of a file management table with bulk processing:
|
|
149
|
+
|
|
150
|
+
```yaml
|
|
151
|
+
renderView:
|
|
152
|
+
- type: table
|
|
153
|
+
content:
|
|
154
|
+
- type: tbody
|
|
155
|
+
content:
|
|
156
|
+
- type: Switch
|
|
157
|
+
content: ~~.files
|
|
158
|
+
singleOption:
|
|
159
|
+
load: fileRow
|
|
160
|
+
|
|
161
|
+
# Bulk action controls
|
|
162
|
+
- type: div
|
|
163
|
+
content:
|
|
164
|
+
- type: SelectField
|
|
165
|
+
dataLocation: ~~.bulkAction
|
|
166
|
+
defaultFieldValue: ""
|
|
167
|
+
options:
|
|
168
|
+
- value: ""
|
|
169
|
+
label: "-- Choose action --"
|
|
170
|
+
- value: "process"
|
|
171
|
+
label: "Process selected files"
|
|
172
|
+
|
|
173
|
+
- type: button
|
|
174
|
+
content: "Execute"
|
|
175
|
+
actions:
|
|
176
|
+
- what: hide
|
|
177
|
+
when: ~~.bulkAction
|
|
178
|
+
isEmpty: true
|
|
179
|
+
- what: triggerEvent
|
|
180
|
+
on: click
|
|
181
|
+
eventName: "click"
|
|
182
|
+
selector: "tr[data-selected=\"true\"] button[data-action=\"process\"]"
|
|
183
|
+
|
|
184
|
+
templates:
|
|
185
|
+
fileRow:
|
|
186
|
+
- type: tr
|
|
187
|
+
actions:
|
|
188
|
+
- what: setAttributeValue
|
|
189
|
+
name: "data-selected"
|
|
190
|
+
value: "true"
|
|
191
|
+
mode: "replace"
|
|
192
|
+
when: ~.selected
|
|
193
|
+
is: true
|
|
194
|
+
- what: setAttributeValue
|
|
195
|
+
name: "data-selected"
|
|
196
|
+
value: "false"
|
|
197
|
+
mode: "replace"
|
|
198
|
+
when: ~.selected
|
|
199
|
+
isNot: true
|
|
200
|
+
content:
|
|
201
|
+
# Checkbox column
|
|
202
|
+
- type: td
|
|
203
|
+
content:
|
|
204
|
+
- type: CheckBoxField
|
|
205
|
+
dataLocation: ~.selected
|
|
206
|
+
defaultFieldValue: false
|
|
207
|
+
options:
|
|
208
|
+
- label: ""
|
|
209
|
+
value: true
|
|
210
|
+
|
|
211
|
+
# File name column
|
|
212
|
+
- type: td
|
|
213
|
+
content: ~.name
|
|
214
|
+
|
|
215
|
+
# Status column
|
|
216
|
+
- type: td
|
|
217
|
+
content: ~.status
|
|
218
|
+
|
|
219
|
+
# Actions column
|
|
220
|
+
- type: td
|
|
221
|
+
content:
|
|
222
|
+
- type: button
|
|
223
|
+
attributes:
|
|
224
|
+
data-action: "process"
|
|
225
|
+
type: "button"
|
|
226
|
+
content: "Process"
|
|
227
|
+
actions:
|
|
228
|
+
- what: hide
|
|
229
|
+
when: ~.status
|
|
230
|
+
is: "processed"
|
|
231
|
+
- what: setData
|
|
232
|
+
on: click
|
|
233
|
+
path: ~.status
|
|
234
|
+
value: "processing"
|
|
235
|
+
- what: submitData
|
|
236
|
+
on: click
|
|
237
|
+
url: "https://api.example.com/process?id=~.id"
|
|
238
|
+
httpMethod: "post"
|
|
239
|
+
allowConcurrent: true
|
|
240
|
+
dataMapping:
|
|
241
|
+
simpleMapping:
|
|
242
|
+
stringMap:
|
|
243
|
+
"~.status":
|
|
244
|
+
value: "processed"
|
|
245
|
+
|
|
246
|
+
data:
|
|
247
|
+
files:
|
|
248
|
+
- id: "file1"
|
|
249
|
+
name: "document.pdf"
|
|
250
|
+
status: "pending"
|
|
251
|
+
selected: false
|
|
252
|
+
- id: "file2"
|
|
253
|
+
name: "image.jpg"
|
|
254
|
+
status: "pending"
|
|
255
|
+
selected: false
|
|
256
|
+
bulkAction: ""
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## How It Works
|
|
260
|
+
|
|
261
|
+
1. **Selection**: Users check boxes to set `~.selected` to `true` for individual items
|
|
262
|
+
2. **Attribute marking**: `setAttributeValue` adds `data-selected="true"` to selected rows
|
|
263
|
+
3. **Bulk trigger**: When "Execute" is clicked, `triggerEvent` finds all `tr[data-selected="true"]` rows
|
|
264
|
+
4. **Action execution**: Within each selected row, it finds `button[data-action="process"]` and triggers a `click` event
|
|
265
|
+
5. **Individual processing**: Each button's `on: click` reactions execute, processing that specific item
|
|
266
|
+
|
|
267
|
+
## Go Further
|
|
268
|
+
|
|
269
|
+
### Select All Functionality
|
|
270
|
+
|
|
271
|
+
Add a "Select All" checkbox in the table header:
|
|
272
|
+
|
|
273
|
+
```yaml
|
|
274
|
+
- type: th
|
|
275
|
+
content:
|
|
276
|
+
- type: CheckBoxField
|
|
277
|
+
dataLocation: ~~.selectAll
|
|
278
|
+
defaultFieldValue: false
|
|
279
|
+
options:
|
|
280
|
+
- label: ""
|
|
281
|
+
value: true
|
|
282
|
+
actions:
|
|
283
|
+
- what: setData
|
|
284
|
+
on: change
|
|
285
|
+
path: ~.selected
|
|
286
|
+
value: ~~.selectAll
|
|
287
|
+
# This would need to be in each row template
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Multiple Action Types
|
|
291
|
+
|
|
292
|
+
Support multiple bulk actions by using different `data-action` values:
|
|
293
|
+
|
|
294
|
+
```yaml
|
|
295
|
+
- type: SelectField
|
|
296
|
+
dataLocation: ~~.bulkAction
|
|
297
|
+
options:
|
|
298
|
+
- value: "process"
|
|
299
|
+
label: "Process"
|
|
300
|
+
- value: "delete"
|
|
301
|
+
label: "Delete"
|
|
302
|
+
- value: "archive"
|
|
303
|
+
label: "Archive"
|
|
304
|
+
|
|
305
|
+
# In triggerEvent, dynamically construct selector:
|
|
306
|
+
- what: triggerEvent
|
|
307
|
+
on: click
|
|
308
|
+
eventName: "click"
|
|
309
|
+
selector: ["tr[data-selected=\"true\"] button[data-action=\"", ~~.bulkAction, "\"]"]
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Visual Feedback
|
|
313
|
+
|
|
314
|
+
Add visual indicators for selected rows using CSS:
|
|
315
|
+
|
|
316
|
+
```yaml
|
|
317
|
+
- type: tr
|
|
318
|
+
attributes:
|
|
319
|
+
class: "bg-white border-b"
|
|
320
|
+
actions:
|
|
321
|
+
- what: setAttributeValue
|
|
322
|
+
name: "class"
|
|
323
|
+
value: "bg-blue-100"
|
|
324
|
+
mode: "append"
|
|
325
|
+
when: ~.selected
|
|
326
|
+
is: true
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### Prevent Double Processing
|
|
330
|
+
|
|
331
|
+
Add conditions to prevent processing items that are already being processed:
|
|
332
|
+
|
|
333
|
+
```yaml
|
|
334
|
+
- type: button
|
|
335
|
+
attributes:
|
|
336
|
+
data-action: "process"
|
|
337
|
+
actions:
|
|
338
|
+
- what: hide
|
|
339
|
+
when: ~.status
|
|
340
|
+
is: "processing"
|
|
341
|
+
- what: hide
|
|
342
|
+
when: ~.status
|
|
343
|
+
is: "processed"
|
|
344
|
+
# Actions only execute if button is visible
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Count Selected Items
|
|
348
|
+
|
|
349
|
+
Display the number of selected items:
|
|
350
|
+
|
|
351
|
+
```yaml
|
|
352
|
+
- type: div
|
|
353
|
+
content:
|
|
354
|
+
- "Selected: "
|
|
355
|
+
- type: Count
|
|
356
|
+
jsonPathPattern: "$.files[?(@.selected == true)]"
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
## Additional Notes
|
|
360
|
+
|
|
361
|
+
### Performance Considerations
|
|
362
|
+
|
|
363
|
+
- **Concurrent requests**: Use `allowConcurrent: true` in `submitData` to process multiple items simultaneously
|
|
364
|
+
- **Selector efficiency**: More specific selectors (like `tr[data-selected="true"]`) are faster than broad selectors
|
|
365
|
+
- **Event delegation**: `triggerEvent` dispatches events sequentially using Promises to ensure reliability
|
|
366
|
+
|
|
367
|
+
### Accessibility
|
|
368
|
+
|
|
369
|
+
- Ensure checkboxes have proper labels
|
|
370
|
+
- Use ARIA attributes for screen readers:
|
|
371
|
+
```yaml
|
|
372
|
+
- what: setAttributeValue
|
|
373
|
+
name: "aria-selected"
|
|
374
|
+
value: "true"
|
|
375
|
+
when: ~.selected
|
|
376
|
+
is: true
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### Error Handling
|
|
380
|
+
|
|
381
|
+
Consider adding error handling for failed bulk operations:
|
|
382
|
+
|
|
383
|
+
```yaml
|
|
384
|
+
- what: submitData
|
|
385
|
+
on: click
|
|
386
|
+
# ... submit configuration
|
|
387
|
+
onError:
|
|
388
|
+
- what: setData
|
|
389
|
+
path: ~.status
|
|
390
|
+
value: "error"
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Alternative Approaches
|
|
394
|
+
|
|
395
|
+
- **Message-based**: Use `postMessage` and `on: message` reactions (more complex but allows cross-component communication)
|
|
396
|
+
- **Custom handlers**: Create a custom React component to handle bulk operations (more control but requires JavaScript)
|
|
397
|
+
|
|
398
|
+
### Best Practices
|
|
399
|
+
|
|
400
|
+
1. **Always use `mode: "replace"`** for `setAttributeValue` when toggling boolean attributes to ensure clean state
|
|
401
|
+
2. **Use specific selectors** to avoid unintended side effects
|
|
402
|
+
3. **Add safety conditions** to prevent actions on inappropriate items
|
|
403
|
+
4. **Provide visual feedback** so users know which items are selected
|
|
404
|
+
5. **Test with multiple selections** to ensure concurrent operations work correctly
|
|
405
|
+
|