@ea-lab/reactive-json-docs 1.2.0 → 1.3.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.
@@ -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
+