@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.
@@ -0,0 +1,514 @@
1
+ renderView:
2
+ - type: Markdown
3
+ content: |
4
+ # Bulk Actions System
5
+
6
+ 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.
7
+
8
+ ## Core Concept
9
+
10
+ The bulk action system uses a combination of:
11
+ - **Selection state**: Track which items are selected using checkboxes
12
+ - **Data attributes**: Mark selected rows in the DOM for CSS selector targeting
13
+ - **Event delegation**: Use `triggerEvent` to programmatically trigger actions on multiple elements
14
+ - **Conditional actions**: Ensure actions only execute on selected items
15
+
16
+ - type: Markdown
17
+ content: |
18
+ ## Concepts We Will Use
19
+
20
+ This pattern leverages several Reactive-JSON features:
21
+
22
+ - **[Switch Component](../element/special/Switch.md)**: Iterate over a collection of items and render each with a template
23
+ - **[SetAttributeValue Action](../action/Attribute/SetAttributeValue.md)**: Dynamically set HTML attributes (like `data-selected`) based on data state
24
+ - **[triggerEvent Reaction](../reaction/triggerEvent.md)**: Programmatically dispatch events on multiple elements matching a CSS selector
25
+ - **[Template Contexts](../getting-started/template-contexts-data-binding.md)**: Use `~.` for row-scoped data and `~~.` for global data
26
+ - **[Conditional Actions](../getting-started/actions.md)**: Use `when` conditions to control when actions execute
27
+
28
+ - type: Markdown
29
+ content: |
30
+ ## Prerequisites
31
+
32
+ Before implementing bulk actions, you should understand:
33
+
34
+ 1. **Template system**: How `Switch` renders items using templates
35
+ 2. **Data binding**: The difference between `~.` (local template context) and `~~.` (global context)
36
+ 3. **Actions and reactions**: How to define actions that respond to user interactions
37
+ 4. **CSS selectors**: Basic understanding of attribute selectors like `[data-selected="true"]`
38
+
39
+ - type: Markdown
40
+ content: |
41
+ ## Steps
42
+
43
+ ### Step 1: Set Up Selection State
44
+
45
+ Add a `selected` property to each item in your data array and a global `bulkAction` variable.
46
+
47
+ - type: SyntaxHighlighter
48
+ language: yaml
49
+ title: "Data Structure"
50
+ content: |
51
+ data:
52
+ items: []
53
+ bulkAction: ""
54
+
55
+ - type: Markdown
56
+ content: |
57
+ Each item in the array should have a `selected` boolean property (can be initialized as `false` or added dynamically).
58
+
59
+ ### Step 2: Add Selection Checkboxes
60
+
61
+ Add checkboxes to each row to allow users to select individual items.
62
+
63
+ - type: SyntaxHighlighter
64
+ language: yaml
65
+ title: "Checkbox in Row Template"
66
+ content: |
67
+ templates:
68
+ itemRow:
69
+ - type: tr
70
+ content:
71
+ - type: td
72
+ content:
73
+ - type: CheckBoxField
74
+ dataLocation: ~.selected
75
+ defaultFieldValue: false
76
+ options:
77
+ - label: ""
78
+ value: true
79
+
80
+ - type: Markdown
81
+ content: |
82
+ ### Step 3: Mark Selected Rows with Data Attributes
83
+
84
+ Use `setAttributeValue` action to add a `data-selected` attribute to rows when they are selected. This allows CSS selectors to target selected rows.
85
+
86
+ - type: SyntaxHighlighter
87
+ language: yaml
88
+ title: "Mark Selected Rows"
89
+ content: |
90
+ templates:
91
+ itemRow:
92
+ - type: tr
93
+ actions:
94
+ - what: setAttributeValue
95
+ name: "data-selected"
96
+ value: "true"
97
+ mode: "replace"
98
+ when: ~.selected
99
+ is: true
100
+ content:
101
+ # ... row content
102
+
103
+ - type: Markdown
104
+ content: |
105
+ **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.
106
+
107
+ ### Step 4: Add Action Buttons with Data Attributes
108
+
109
+ Add `data-action` attributes to action buttons so they can be targeted by CSS selectors.
110
+
111
+ - type: SyntaxHighlighter
112
+ language: yaml
113
+ title: "Action Button with Data Attribute"
114
+ content: |
115
+ - type: button
116
+ attributes:
117
+ data-action: "process"
118
+ type: "button"
119
+ content: "Process"
120
+ actions:
121
+ - what: submitData
122
+ on: click
123
+ # ... action configuration
124
+
125
+ - type: Markdown
126
+ content: |
127
+ ### Step 5: Create Bulk Action Controls
128
+
129
+ Add a bulk action selector and execute button in your main view.
130
+
131
+ - type: SyntaxHighlighter
132
+ language: yaml
133
+ title: "Bulk Action Controls"
134
+ content: |
135
+ renderView:
136
+ - type: SelectField
137
+ dataLocation: ~~.bulkAction
138
+ defaultFieldValue: ""
139
+ options:
140
+ - value: ""
141
+ label: "-- Choose action --"
142
+ - value: "process"
143
+ label: "Process selected items"
144
+
145
+ - type: button
146
+ content: "Execute"
147
+ actions:
148
+ - what: hide
149
+ when: ~~.bulkAction
150
+ isEmpty: true
151
+ - what: triggerEvent
152
+ on: click
153
+ eventName: "click"
154
+ selector: "tr[data-selected=\"true\"] button[data-action=\"process\"]"
155
+
156
+ - type: Markdown
157
+ content: |
158
+ ### Step 6: Add Safety Conditions
159
+
160
+ Add conditions to prevent actions from executing on items that shouldn't be processed.
161
+
162
+ - type: SyntaxHighlighter
163
+ language: yaml
164
+ title: "Safety Conditions"
165
+ content: |
166
+ - type: button
167
+ attributes:
168
+ data-action: "process"
169
+ actions:
170
+ - what: hide
171
+ when: ~.status
172
+ is: "processed" # Hide button if already processed
173
+ - what: submitData
174
+ on: click
175
+ # ... only executes if button is visible
176
+
177
+ - type: RjBuildDescriber
178
+ title: "Complete Example: File Management Table"
179
+ description: |
180
+ A complete example of a file management table with bulk processing. Users can select multiple files and process them all at once by clicking the "Execute" button.
181
+ toDescribe:
182
+ renderView:
183
+ - type: div
184
+ attributes:
185
+ class: "p-4"
186
+ content:
187
+ - type: h2
188
+ attributes:
189
+ class: "text-2xl font-bold mb-4"
190
+ content: "File Management"
191
+
192
+ - type: table
193
+ attributes:
194
+ class: "w-full border-collapse border border-gray-300 mb-4"
195
+ content:
196
+ - type: thead
197
+ content:
198
+ - type: tr
199
+ content:
200
+ - type: th
201
+ attributes:
202
+ class: "border border-gray-300 p-2 bg-gray-100"
203
+ content: "Select"
204
+ - type: th
205
+ attributes:
206
+ class: "border border-gray-300 p-2 bg-gray-100"
207
+ content: "File Name"
208
+ - type: th
209
+ attributes:
210
+ class: "border border-gray-300 p-2 bg-gray-100"
211
+ content: "Status"
212
+ - type: th
213
+ attributes:
214
+ class: "border border-gray-300 p-2 bg-gray-100"
215
+ content: "Actions"
216
+ - type: tbody
217
+ content:
218
+ - type: Switch
219
+ content: ~~.files
220
+ singleOption:
221
+ load: fileRow
222
+
223
+ - type: div
224
+ attributes:
225
+ class: "flex items-center gap-4 p-4 bg-gray-100 rounded"
226
+ content:
227
+ - type: label
228
+ attributes:
229
+ class: "font-medium"
230
+ content: "Bulk action:"
231
+ - type: SelectField
232
+ dataLocation: ~~.bulkAction
233
+ defaultFieldValue: ""
234
+ inputAttributes:
235
+ class: "border border-gray-300 p-2 rounded"
236
+ options:
237
+ - value: ""
238
+ label: "-- Choose action --"
239
+ - value: "process"
240
+ label: "Process selected files"
241
+
242
+ - type: button
243
+ attributes:
244
+ class: "bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
245
+ content: "Execute"
246
+ actions:
247
+ - what: hide
248
+ when: ~~.bulkAction
249
+ isEmpty: true
250
+ - what: triggerEvent
251
+ on: click
252
+ eventName: "click"
253
+ selector: "tr[data-selected=\"true\"] button[data-action=\"process\"]"
254
+
255
+ templates:
256
+ fileRow:
257
+ - type: tr
258
+ attributes:
259
+ class: "bg-white border-b"
260
+ actions:
261
+ - what: setAttributeValue
262
+ name: "data-selected"
263
+ value: "true"
264
+ mode: "replace"
265
+ when: ~.selected
266
+ is: true
267
+ - what: setAttributeValue
268
+ name: "data-selected"
269
+ value: "false"
270
+ mode: "replace"
271
+ when: ~.selected
272
+ isNot: true
273
+ content:
274
+ - type: td
275
+ attributes:
276
+ class: "border border-gray-300 p-2"
277
+ content:
278
+ - type: CheckBoxField
279
+ dataLocation: ~.selected
280
+ defaultFieldValue: false
281
+ options:
282
+ - label: ""
283
+ value: true
284
+ attributes:
285
+ class: "w-4 h-4"
286
+
287
+ - type: td
288
+ attributes:
289
+ class: "border border-gray-300 p-2"
290
+ content: ~.name
291
+
292
+ - type: td
293
+ attributes:
294
+ class: "border border-gray-300 p-2"
295
+ content:
296
+ - type: span
297
+ attributes:
298
+ class: "px-2 py-1 rounded text-xs"
299
+ content: ~.status
300
+
301
+ - type: td
302
+ attributes:
303
+ class: "border border-gray-300 p-2"
304
+ content:
305
+ - type: button
306
+ attributes:
307
+ data-action: "process"
308
+ class: "bg-blue-500 text-white px-3 py-1 rounded text-sm hover:bg-blue-600"
309
+ type: "button"
310
+ content: "Process"
311
+ actions:
312
+ - what: hide
313
+ when: ~.status
314
+ is: "processing"
315
+ - what: hide
316
+ when: ~.status
317
+ is: "processed"
318
+ - what: setData
319
+ on: click
320
+ path: ~.status
321
+ value: "processing"
322
+ - what: setData
323
+ on: click
324
+ path: ~.status
325
+ value: "processed"
326
+ delay: 2000
327
+
328
+ data:
329
+ files:
330
+ - id: "file1"
331
+ name: "document.pdf"
332
+ status: "pending"
333
+ selected: false
334
+ - id: "file2"
335
+ name: "image.jpg"
336
+ status: "pending"
337
+ selected: false
338
+ - id: "file3"
339
+ name: "spreadsheet.xlsx"
340
+ status: "pending"
341
+ selected: false
342
+ bulkAction: ""
343
+
344
+ - type: Markdown
345
+ content: |
346
+ ## How It Works
347
+
348
+ 1. **Selection**: Users check boxes to set `~.selected` to `true` for individual items
349
+ 2. **Attribute marking**: `setAttributeValue` adds `data-selected="true"` to selected rows
350
+ 3. **Bulk trigger**: When "Execute" is clicked, `triggerEvent` finds all `tr[data-selected="true"]` rows
351
+ 4. **Action execution**: Within each selected row, it finds `button[data-action="process"]` and triggers a `click` event
352
+ 5. **Individual processing**: Each button's `on: click` reactions execute, processing that specific item
353
+
354
+ - type: Markdown
355
+ content: |
356
+ ## Go Further
357
+
358
+ ### Select All Functionality
359
+
360
+ Add a "Select All" checkbox in the table header to select/deselect all items at once.
361
+
362
+ - type: SyntaxHighlighter
363
+ language: yaml
364
+ title: "Select All Checkbox"
365
+ content: |
366
+ - type: th
367
+ content:
368
+ - type: CheckBoxField
369
+ dataLocation: ~~.selectAll
370
+ defaultFieldValue: false
371
+ options:
372
+ - label: ""
373
+ value: true
374
+ actions:
375
+ - what: setData
376
+ on: change
377
+ path: ~.selected
378
+ value: ~~.selectAll
379
+ # This would need to be in each row template
380
+
381
+ - type: Markdown
382
+ content: |
383
+ ### Multiple Action Types
384
+
385
+ Support multiple bulk actions by using different `data-action` values and dynamically constructing the selector.
386
+
387
+ - type: SyntaxHighlighter
388
+ language: yaml
389
+ title: "Multiple Bulk Actions"
390
+ content: |
391
+ - type: SelectField
392
+ dataLocation: ~~.bulkAction
393
+ options:
394
+ - value: "process"
395
+ label: "Process"
396
+ - value: "delete"
397
+ label: "Delete"
398
+ - value: "archive"
399
+ label: "Archive"
400
+
401
+ # In triggerEvent, dynamically construct selector:
402
+ - what: triggerEvent
403
+ on: click
404
+ eventName: "click"
405
+ selector: ["tr[data-selected=\"true\"] button[data-action=\"", ~~.bulkAction, "\"]"]
406
+
407
+ - type: Markdown
408
+ content: |
409
+ ### Visual Feedback
410
+
411
+ Add visual indicators for selected rows using CSS classes.
412
+
413
+ - type: SyntaxHighlighter
414
+ language: yaml
415
+ title: "Visual Feedback for Selected Rows"
416
+ content: |
417
+ - type: tr
418
+ attributes:
419
+ class: "bg-white border-b"
420
+ actions:
421
+ - what: setAttributeValue
422
+ name: "class"
423
+ value: "bg-blue-100"
424
+ mode: "append"
425
+ when: ~.selected
426
+ is: true
427
+
428
+ - type: Markdown
429
+ content: |
430
+ ### Prevent Double Processing
431
+
432
+ Add conditions to prevent processing items that are already being processed.
433
+
434
+ - type: SyntaxHighlighter
435
+ language: yaml
436
+ title: "Prevent Double Processing"
437
+ content: |
438
+ - type: button
439
+ attributes:
440
+ data-action: "process"
441
+ actions:
442
+ - what: hide
443
+ when: ~.status
444
+ is: "processing"
445
+ - what: hide
446
+ when: ~.status
447
+ is: "processed"
448
+ # Actions only execute if button is visible
449
+
450
+ - type: Markdown
451
+ content: |
452
+ ### Count Selected Items
453
+
454
+ Display the number of selected items using the `Count` component.
455
+
456
+ - type: SyntaxHighlighter
457
+ language: yaml
458
+ title: "Display Selection Count"
459
+ content: |
460
+ - type: div
461
+ content:
462
+ - "Selected: "
463
+ - type: Count
464
+ jsonPathPattern: "$.files[?(@.selected == true)]"
465
+
466
+ - type: Markdown
467
+ content: |
468
+ ## Additional Notes
469
+
470
+ ### Performance Considerations
471
+
472
+ - **Concurrent requests**: Use `allowConcurrent: true` in `submitData` to process multiple items simultaneously
473
+ - **Selector efficiency**: More specific selectors (like `tr[data-selected="true"]`) are faster than broad selectors
474
+ - **Event delegation**: `triggerEvent` dispatches events sequentially using Promises to ensure reliability
475
+
476
+ ### Accessibility
477
+
478
+ - Ensure checkboxes have proper labels
479
+ - Use ARIA attributes for screen readers:
480
+ ```yaml
481
+ - what: setAttributeValue
482
+ name: "aria-selected"
483
+ value: "true"
484
+ when: ~.selected
485
+ is: true
486
+ ```
487
+
488
+ ### Error Handling
489
+
490
+ Consider adding error handling for failed bulk operations:
491
+
492
+ ```yaml
493
+ - what: submitData
494
+ on: click
495
+ # ... submit configuration
496
+ onError:
497
+ - what: setData
498
+ path: ~.status
499
+ value: "error"
500
+ ```
501
+
502
+ ### Alternative Approaches
503
+
504
+ - **Message-based**: Use `postMessage` and `on: message` reactions (more complex but allows cross-component communication)
505
+ - **Custom handlers**: Create a custom React component to handle bulk operations (more control but requires JavaScript)
506
+
507
+ ### Best Practices
508
+
509
+ 1. **Always use `mode: "replace"`** for `setAttributeValue` when toggling boolean attributes to ensure clean state
510
+ 2. **Use specific selectors** to avoid unintended side effects
511
+ 3. **Add safety conditions** to prevent actions on inappropriate items
512
+ 4. **Provide visual feedback** so users know which items are selected
513
+ 5. **Test with multiple selections** to ensure concurrent operations work correctly
514
+