@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,281 @@
1
+ # Editable Modal in Row Template
2
+
3
+ This guide demonstrates a pattern for creating editable modals within row templates, allowing users to edit individual items in a list without complex state management or custom handlers.
4
+
5
+ ## Core Concept
6
+
7
+ By placing a modal inside a row template (using `Switch`), each row gets its own modal instance with direct access to the row's data via the `~.` notation. This simplifies data flow and eliminates the need for complex index tracking or custom save handlers.
8
+
9
+ ## Key Benefits
10
+
11
+ 1. **Simplified data access**: Modal has direct access to row data via `~.` notation
12
+ 2. **No index tracking**: No need to find array indices or store file IDs
13
+ 3. **Automatic isolation**: Each row's modal is isolated from others
14
+ 4. **Simple save pattern**: Use basic `setData` reactions to copy editable values back to originals
15
+
16
+ ## Prerequisites
17
+
18
+ Before implementing this pattern, you need:
19
+
20
+ 1. **A Reactive-JSON Modal component**: This pattern requires a Modal component implementation that supports:
21
+ - `showBoolPath` property (or equivalent) to control visibility via data path
22
+ - `headerTitle` property for the modal header
23
+ - `body` property for the modal content
24
+ - Integration with Reactive-JSON's action system
25
+
26
+ You can use a custom Modal component or one from an integration package (like `@ea-lab/reactive-json-bootstrap`), but it must be compatible with Reactive-JSON's component system.
27
+
28
+ ## Pattern Structure
29
+
30
+ ### 1. Modal Inside Row Template
31
+
32
+ Place the modal component inside your row template so each rendered row has its own modal instance:
33
+
34
+ ```yaml
35
+ templates:
36
+ itemRow:
37
+ - type: tr
38
+ content:
39
+ # Row content (cells, buttons, etc.)
40
+ - type: button
41
+ content: "Edit"
42
+ actions:
43
+ - what: setData
44
+ on: click
45
+ path: ~.showModal
46
+ value: true
47
+
48
+ # Modal inside the row
49
+ - type: ReactiveJsonSubroot
50
+ sharedUpdates: true
51
+ rjOptions:
52
+ rjBuildUrl: "/components/EditModal.yaml"
53
+ dataOverride:
54
+ showModal: ~.showModal
55
+ # ... other data
56
+ ```
57
+
58
+ ### 2. Separate Editable Values
59
+
60
+ Use separate fields for editable copies and original values:
61
+
62
+ ```yaml
63
+ dataOverride:
64
+ # Original values (read-only display)
65
+ id: ~.id
66
+ name: ~.name
67
+
68
+ # Editable copies (for form fields)
69
+ editable_name: ~.editable.name
70
+ editable_description: ~.editable.description
71
+
72
+ # Original values (for saving back)
73
+ name: ~.name
74
+ description: ~.description
75
+ ```
76
+
77
+ ### 3. Initialize Editable Values
78
+
79
+ When opening the modal, copy original values to editable fields:
80
+
81
+ ```yaml
82
+ - type: button
83
+ content: "Edit"
84
+ actions:
85
+ - what: setData
86
+ on: click
87
+ path: ~.editable.name
88
+ value: ~.name
89
+ - what: setData
90
+ on: click
91
+ path: ~.editable.description
92
+ value: ~.description
93
+ - what: setData
94
+ on: click
95
+ path: ~.showModal
96
+ value: true
97
+ ```
98
+
99
+ ### 4. Save Pattern
100
+
101
+ Use simple `setData` reactions to copy editable values back to originals:
102
+
103
+ ```yaml
104
+ - type: button
105
+ content: "Save"
106
+ actions:
107
+ - what: setData
108
+ on: click
109
+ path: ~.name
110
+ value: ~.editable_name
111
+ - what: setData
112
+ on: click
113
+ path: ~.description
114
+ value: ~.editable_description
115
+ - what: setData
116
+ on: click
117
+ path: ~.showModal
118
+ value: false
119
+ ```
120
+
121
+ ## Complete Example
122
+
123
+ ### Parent Component (Table with Rows)
124
+
125
+ ```yaml
126
+ renderView:
127
+ - type: table
128
+ content:
129
+ - type: tbody
130
+ content:
131
+ - type: Switch
132
+ content: ~~.items
133
+ singleOption:
134
+ load: itemRow
135
+
136
+ templates:
137
+ itemRow:
138
+ - type: tr
139
+ content:
140
+ - type: td
141
+ content: ~.name
142
+ - type: td
143
+ content:
144
+ - type: button
145
+ content: "Edit"
146
+ actions:
147
+ - what: setData
148
+ on: click
149
+ path: ~.editable.name
150
+ value: ~.name
151
+ - what: setData
152
+ on: click
153
+ path: ~.editable.description
154
+ value: ~.description
155
+ - what: setData
156
+ on: click
157
+ path: ~.showModal
158
+ value: true
159
+
160
+ # Modal inside the row
161
+ - type: ReactiveJsonSubroot
162
+ sharedUpdates: true
163
+ rjOptions:
164
+ rjBuildUrl: "/components/EditModal.yaml"
165
+ dataOverride:
166
+ showModal: ~.showModal
167
+ id: ~.id
168
+ name: ~.name
169
+ editable_name: ~.editable.name
170
+ editable_description: ~.editable.description
171
+ name: ~.name
172
+ description: ~.description
173
+
174
+ data:
175
+ items:
176
+ - id: 1
177
+ name: "Item 1"
178
+ description: "Description 1"
179
+ showModal: false
180
+ editable:
181
+ name: ""
182
+ description: ""
183
+ ```
184
+
185
+ ### Modal Component (`/components/EditModal.yaml`)
186
+
187
+ ```yaml
188
+ renderView:
189
+ - type: Modal
190
+ showBoolPath: ~.showModal
191
+ headerTitle: "Edit Item"
192
+ body:
193
+ - type: TextField
194
+ label: "Name:"
195
+ dataLocation: ~.editable_name
196
+ - type: TextAreaField
197
+ label: "Description:"
198
+ dataLocation: ~.editable_description
199
+ rows: 3
200
+ footer:
201
+ - type: button
202
+ content: "Cancel"
203
+ actions:
204
+ - what: setData
205
+ on: click
206
+ path: ~.showModal
207
+ value: false
208
+ - type: button
209
+ content: "Save"
210
+ actions:
211
+ - what: setData
212
+ on: click
213
+ path: ~.name
214
+ value: ~.editable_name
215
+ - what: setData
216
+ on: click
217
+ path: ~.description
218
+ value: ~.editable_description
219
+ - what: setData
220
+ on: click
221
+ path: ~.showModal
222
+ value: false
223
+
224
+ data:
225
+ showModal: false
226
+ id: ""
227
+ name: ""
228
+ editable_name: ""
229
+ editable_description: ""
230
+ description: ""
231
+ ```
232
+
233
+ ## How It Works
234
+
235
+ 1. **Row Context**: Each row rendered by `Switch` has its own template context, accessible via `~.`
236
+ 2. **Modal Access**: The modal inside the row inherits this context, so `~.name` refers to the current row's name
237
+ 3. **Editable Copies**: Form fields bind to `~.editable_name` (or `~.editable.name`), keeping edits separate from originals
238
+ 4. **Save Action**: When saving, `setData` with `path: ~.name` and `value: ~.editable_name` copies the edited value back to the original
239
+ 5. **Shared Updates**: With `sharedUpdates: true`, changes to `~.name` in the modal propagate back to the row's data
240
+
241
+ ## Advantages Over Alternative Approaches
242
+
243
+ ### ❌ Complex Approach (Not Recommended)
244
+ - Store file index globally
245
+ - Use custom handlers to find and update array items
246
+ - Requires complex path construction with array indices
247
+
248
+ ### ✅ Simple Approach (This Pattern)
249
+ - Modal is in row context - direct access via `~.`
250
+ - No index tracking needed
251
+ - Simple `setData` actions copy values back
252
+ - Works seamlessly with `sharedUpdates`
253
+
254
+ ## Best Practices
255
+
256
+ 1. **Use `sharedUpdates: true`**: Enables automatic data synchronization between modal and row
257
+ 2. **Separate editable fields**: Keep editable copies separate from originals for clean cancel behavior
258
+ 3. **Initialize on open**: Copy original values to editable fields when opening the modal
259
+ 4. **Simple save pattern**: Use straightforward `setData` actions to copy editable values back
260
+ 5. **Row-scoped modals**: Place modals inside row templates to leverage template context
261
+
262
+ ## Use Cases
263
+
264
+ - **Data tables**: Edit individual rows without affecting others
265
+ - **List items**: Modify properties of items in a list
266
+ - **Card grids**: Edit cards in a grid layout
267
+ - **Nested data**: Edit nested objects within arrays
268
+
269
+ ## Limitations
270
+
271
+ - Each row renders its own modal instance (may impact performance with very large lists)
272
+ - Modal state is tied to row data (if row is removed, modal state is lost)
273
+ - Not suitable for modals that need to persist across row re-renders
274
+
275
+ ## Related Patterns
276
+
277
+ - **ReactiveJsonSubroot**: Component used to embed the modal
278
+ - **Switch**: Component used to render rows with templates
279
+ - **setData**: Reaction used to save edited values
280
+ - **sharedUpdates**: Feature enabling bidirectional data sync
281
+
@@ -0,0 +1,415 @@
1
+ renderView:
2
+ - type: Markdown
3
+ content: |
4
+ # Editable Modal in Row Template
5
+
6
+ This guide demonstrates a pattern for creating editable modals within row templates, allowing users to edit individual items in a list without complex state management or custom handlers.
7
+
8
+ ## Core Concept
9
+
10
+ By placing a modal inside a row template (using `Switch`), each row gets its own modal instance with direct access to the row's data via the `~.` notation. This simplifies data flow and eliminates the need for complex index tracking or custom save handlers.
11
+
12
+ - type: Markdown
13
+ content: |
14
+ ## Key Benefits
15
+
16
+ 1. **Simplified data access**: Modal has direct access to row data via `~.` notation
17
+ 2. **No index tracking**: No need to find array indices or store file IDs
18
+ 3. **Automatic isolation**: Each row's modal is isolated from others
19
+ 4. **Simple save pattern**: Use basic `setData` reactions to copy editable values back to originals
20
+
21
+ - type: Markdown
22
+ content: |
23
+ ## Prerequisites
24
+
25
+ Before implementing this pattern, you need:
26
+
27
+ 1. **A Reactive-JSON Modal component**: This pattern requires a Modal component implementation that supports:
28
+ - `showBoolPath` property (or equivalent) to control visibility via data path
29
+ - `headerTitle` property for the modal header
30
+ - `body` property for the modal content
31
+ - Integration with Reactive-JSON's action system
32
+
33
+ You can use a custom Modal component or one from an integration package (like `@ea-lab/reactive-json-bootstrap`), but it must be compatible with Reactive-JSON's component system.
34
+
35
+ - type: Markdown
36
+ content: |
37
+ ## Pattern Structure
38
+
39
+ ### 1. Modal Inside Row Template
40
+
41
+ Place the modal component inside your row template so each rendered row has its own modal instance.
42
+
43
+ - type: SyntaxHighlighter
44
+ language: yaml
45
+ title: "Modal Inside Row Template"
46
+ content: |
47
+ templates:
48
+ itemRow:
49
+ - type: tr
50
+ content:
51
+ # Row content (cells, buttons, etc.)
52
+ - type: button
53
+ content: "Edit"
54
+ actions:
55
+ - what: setData
56
+ on: click
57
+ path: ~.showModal
58
+ value: true
59
+
60
+ # Modal inside the row
61
+ - type: ReactiveJsonSubroot
62
+ sharedUpdates: true
63
+ rjOptions:
64
+ rjBuildUrl: "/components/EditModal.yaml"
65
+ dataOverride:
66
+ showModal: ~.showModal
67
+ # ... other data
68
+
69
+ - type: Markdown
70
+ content: |
71
+ ### 2. Separate Editable Values
72
+
73
+ Use separate fields for editable copies and original values.
74
+
75
+ - type: SyntaxHighlighter
76
+ language: yaml
77
+ title: "Data Override Structure"
78
+ content: |
79
+ dataOverride:
80
+ # Original values (read-only display)
81
+ id: ~.id
82
+ name: ~.name
83
+
84
+ # Editable copies (for form fields)
85
+ editable_name: ~.editable.name
86
+ editable_description: ~.editable.description
87
+
88
+ # Original values (for saving back)
89
+ name: ~.name
90
+ description: ~.description
91
+
92
+ - type: Markdown
93
+ content: |
94
+ ### 3. Initialize Editable Values
95
+
96
+ When opening the modal, copy original values to editable fields.
97
+
98
+ - type: SyntaxHighlighter
99
+ language: yaml
100
+ title: "Initialize Editable Values"
101
+ content: |
102
+ - type: button
103
+ content: "Edit"
104
+ actions:
105
+ - what: setData
106
+ on: click
107
+ path: ~.editable.name
108
+ value: ~.name
109
+ - what: setData
110
+ on: click
111
+ path: ~.editable.description
112
+ value: ~.description
113
+ - what: setData
114
+ on: click
115
+ path: ~.showModal
116
+ value: true
117
+
118
+ - type: Markdown
119
+ content: |
120
+ ### 4. Save Pattern
121
+
122
+ Use simple `setData` reactions to copy editable values back to originals.
123
+
124
+ - type: SyntaxHighlighter
125
+ language: yaml
126
+ title: "Save Button Actions"
127
+ content: |
128
+ - type: button
129
+ content: "Save"
130
+ actions:
131
+ - what: setData
132
+ on: click
133
+ path: ~.name
134
+ value: ~.editable_name
135
+ - what: setData
136
+ on: click
137
+ path: ~.description
138
+ value: ~.editable_description
139
+ - what: setData
140
+ on: click
141
+ path: ~.showModal
142
+ value: false
143
+
144
+ - type: RjBuildDescriber
145
+ title: "Complete Example: Editable Item List"
146
+ description: |
147
+ A complete example showing a table with editable rows. Each row has an "Edit" button that opens a modal. The modal allows editing the item's name and description, with Save and Cancel buttons.
148
+ toDescribe:
149
+ renderView:
150
+ - type: div
151
+ attributes:
152
+ class: "p-4"
153
+ content:
154
+ - type: h2
155
+ attributes:
156
+ class: "text-2xl font-bold mb-4"
157
+ content: "Items List"
158
+ - type: table
159
+ attributes:
160
+ class: "w-full border-collapse border border-gray-300"
161
+ content:
162
+ - type: thead
163
+ content:
164
+ - type: tr
165
+ content:
166
+ - type: th
167
+ attributes:
168
+ class: "border border-gray-300 p-2 bg-gray-100"
169
+ content: "ID"
170
+ - type: th
171
+ attributes:
172
+ class: "border border-gray-300 p-2 bg-gray-100"
173
+ content: "Name"
174
+ - type: th
175
+ attributes:
176
+ class: "border border-gray-300 p-2 bg-gray-100"
177
+ content: "Description"
178
+ - type: th
179
+ attributes:
180
+ class: "border border-gray-300 p-2 bg-gray-100"
181
+ content: "Actions"
182
+ - type: tbody
183
+ content:
184
+ - type: Switch
185
+ content: ~~.items
186
+ singleOption:
187
+ load: itemRow
188
+ - type: div
189
+ attributes:
190
+ class: "mt-4 p-2 bg-gray-100 rounded"
191
+ content:
192
+ - type: strong
193
+ content: "Debug - First item name: "
194
+ - type: span
195
+ content: ~~.items.0.name
196
+
197
+ templates:
198
+ itemRow:
199
+ - type: tr
200
+ content:
201
+ - type: td
202
+ attributes:
203
+ class: "border border-gray-300 p-2"
204
+ content: ~.id
205
+ - type: td
206
+ attributes:
207
+ class: "border border-gray-300 p-2"
208
+ content: ~.name
209
+ - type: td
210
+ attributes:
211
+ class: "border border-gray-300 p-2"
212
+ content: ~.description
213
+ - type: td
214
+ attributes:
215
+ class: "border border-gray-300 p-2"
216
+ content:
217
+ - type: button
218
+ attributes:
219
+ class: "bg-blue-500 text-white px-3 py-1 rounded hover:bg-blue-600"
220
+ content: "Edit"
221
+ actions:
222
+ - what: setData
223
+ on: click
224
+ path: ~.editable.name
225
+ value: ~.name
226
+ - what: setData
227
+ on: click
228
+ path: ~.editable.description
229
+ value: ~.description
230
+ - what: setData
231
+ on: click
232
+ path: ~.showModal
233
+ value: true
234
+
235
+ # Modal inside the row
236
+ - type: ReactiveJsonSubroot
237
+ sharedUpdates: true
238
+ rjOptions:
239
+ maybeRawAppRjBuild:
240
+ renderView:
241
+ - type: Modal
242
+ showBoolPath: ~.showModal
243
+ headerTitle:
244
+ type: h3
245
+ attributes:
246
+ class: "text-xl font-semibold"
247
+ content: "Edit Item"
248
+ body:
249
+ - type: div
250
+ attributes:
251
+ class: "space-y-4"
252
+ content:
253
+ - type: div
254
+ content:
255
+ - type: label
256
+ attributes:
257
+ class: "block text-sm font-medium mb-1"
258
+ content: "ID (read-only):"
259
+ - type: div
260
+ attributes:
261
+ class: "p-2 bg-gray-100 rounded"
262
+ content: ~.id
263
+ - type: div
264
+ content:
265
+ - type: label
266
+ attributes:
267
+ class: "block text-sm font-medium mb-1"
268
+ content: "Name:"
269
+ - type: TextField
270
+ dataLocation: ~.editable_name
271
+ forceWrapper: false
272
+ inputAttributes:
273
+ class: "w-full p-2 border border-gray-300 rounded"
274
+ - type: div
275
+ content:
276
+ - type: label
277
+ attributes:
278
+ class: "block text-sm font-medium mb-1"
279
+ content: "Description:"
280
+ - type: TextAreaField
281
+ dataLocation: ~.editable_description
282
+ forceWrapper: false
283
+ rows: 3
284
+ inputAttributes:
285
+ class: "w-full p-2 border border-gray-300 rounded"
286
+ - type: div
287
+ attributes:
288
+ class: "flex justify-end gap-2 mt-4 pt-4 border-t border-gray-200 dark:border-gray-700"
289
+ content:
290
+ - type: button
291
+ attributes:
292
+ class: "px-4 py-2 bg-gray-300 rounded hover:bg-gray-400"
293
+ content: "Cancel"
294
+ actions:
295
+ - what: setData
296
+ on: click
297
+ path: ~.showModal
298
+ value: false
299
+ - type: button
300
+ attributes:
301
+ class: "px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
302
+ content: "Save"
303
+ actions:
304
+ - what: setData
305
+ on: click
306
+ path: ~.name
307
+ value: ~.editable_name
308
+ - what: setData
309
+ on: click
310
+ path: ~.description
311
+ value: ~.editable_description
312
+ - what: setData
313
+ on: click
314
+ path: ~.showModal
315
+ value: false
316
+ data:
317
+ showModal: false
318
+ id: ""
319
+ name: ""
320
+ editable_name: ""
321
+ editable_description: ""
322
+ description: ""
323
+ dataOverride:
324
+ showModal: ~.showModal
325
+ id: ~.id
326
+ name: ~.name
327
+ editable_name: ~.editable.name
328
+ editable_description: ~.editable.description
329
+ description: ~.description
330
+
331
+ data:
332
+ items:
333
+ - id: 1
334
+ name: "First Item"
335
+ description: "This is the first item's description"
336
+ showModal: false
337
+ editable:
338
+ name: ""
339
+ description: ""
340
+ - id: 2
341
+ name: "Second Item"
342
+ description: "This is the second item's description"
343
+ showModal: false
344
+ editable:
345
+ name: ""
346
+ description: ""
347
+ - id: 3
348
+ name: "Third Item"
349
+ description: "This is the third item's description"
350
+ showModal: false
351
+ editable:
352
+ name: ""
353
+ description: ""
354
+
355
+ - type: Markdown
356
+ content: |
357
+ ## How It Works
358
+
359
+ 1. **Row Context**: Each row rendered by `Switch` has its own template context, accessible via `~.`
360
+ 2. **Modal Access**: The modal inside the row inherits this context, so `~.name` refers to the current row's name
361
+ 3. **Editable Copies**: Form fields bind to `~.editable_name` (or `~.editable.name`), keeping edits separate from originals
362
+ 4. **Save Action**: When saving, `setData` with `path: ~.name` and `value: ~.editable_name` copies the edited value back to the original
363
+ 5. **Shared Updates**: With `sharedUpdates: true`, changes to `~.name` in the modal propagate back to the row's data
364
+
365
+ - type: Markdown
366
+ content: |
367
+ ## Advantages Over Alternative Approaches
368
+
369
+ ### ❌ Complex Approach (Not Recommended)
370
+ - Store file index globally
371
+ - Use custom handlers to find and update array items
372
+ - Requires complex path construction with array indices
373
+
374
+ ### ✅ Simple Approach (This Pattern)
375
+ - Modal is in row context - direct access via `~.`
376
+ - No index tracking needed
377
+ - Simple `setData` actions copy values back
378
+ - Works seamlessly with `sharedUpdates`
379
+
380
+ - type: Markdown
381
+ content: |
382
+ ## Best Practices
383
+
384
+ 1. **Use `sharedUpdates: true`**: Enables automatic data synchronization between modal and row
385
+ 2. **Separate editable fields**: Keep editable copies separate from originals for clean cancel behavior
386
+ 3. **Initialize on open**: Copy original values to editable fields when opening the modal
387
+ 4. **Simple save pattern**: Use straightforward `setData` actions to copy editable values back
388
+ 5. **Row-scoped modals**: Place modals inside row templates to leverage template context
389
+
390
+ - type: Markdown
391
+ content: |
392
+ ## Use Cases
393
+
394
+ - **Data tables**: Edit individual rows without affecting others
395
+ - **List items**: Modify properties of items in a list
396
+ - **Card grids**: Edit cards in a grid layout
397
+ - **Nested data**: Edit nested objects within arrays
398
+
399
+ - type: Markdown
400
+ content: |
401
+ ## Limitations
402
+
403
+ - Each row renders its own modal instance (may impact performance with very large lists)
404
+ - Modal state is tied to row data (if row is removed, modal state is lost)
405
+ - Not suitable for modals that need to persist across row re-renders
406
+
407
+ - type: Markdown
408
+ content: |
409
+ ## Related Patterns
410
+
411
+ - **ReactiveJsonSubroot**: Component used to embed the modal
412
+ - **Switch**: Component used to render rows with templates
413
+ - **setData**: Reaction used to save edited values
414
+ - **sharedUpdates**: Feature enabling bidirectional data sync
415
+