@ea-lab/reactive-json-docs 1.3.0 → 1.4.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,209 @@
1
+ # Conditional Field with Dual Data Update Pattern
2
+
3
+ This example demonstrates a pattern where a `SelectField` controls both its own value and another field's value, while a `TextAreaField` conditionally appears and changes its `readonly` state based on the selection.
4
+
5
+ ## Use Case
6
+
7
+ You have a form where:
8
+ 1. A `SelectField` allows choosing between predefined options or a custom value
9
+ 2. When a predefined option is selected, a `TextAreaField` is automatically filled and becomes readonly
10
+ 3. When "custom" is selected, the `TextAreaField` becomes editable and appears
11
+ 4. Both fields only appear when a prerequisite condition is met (e.g., another field is filled)
12
+
13
+ ## Pattern Structure
14
+
15
+ ### Key Concepts
16
+
17
+ - **Dual Data Update**: The `SelectField` updates two data paths simultaneously:
18
+ - Its own value (`instructionType`)
19
+ - The dependent field's value (`instruction`)
20
+ - **Conditional Visibility**: Fields appear only when prerequisite data exists
21
+ - **Dynamic Readonly State**: The `TextAreaField`'s `readonly` attribute changes based on selection
22
+
23
+ ### Implementation
24
+
25
+ ```yaml
26
+ renderView:
27
+ # SelectField that controls both its value and another field
28
+ - type: SelectField
29
+ dataLocation: ~~.formData.instructionType
30
+ defaultFieldValue: "_"
31
+ dynamicOptions: ~~.instructionOptions
32
+ label: "Instructions"
33
+ actions:
34
+ # Hide if prerequisite condition not met
35
+ - isEmpty: true
36
+ when: ~~.formData.sheet
37
+ what: hide
38
+ # Update the dependent field's value (direct copy)
39
+ - what: setData
40
+ on: change
41
+ path: ~~.formData.instruction
42
+ value: <reactive-json:event-new-value>
43
+ # Update its own value (redundant but explicit)
44
+ - what: setData
45
+ on: change
46
+ path: ~~.formData.instructionType
47
+ value: <reactive-json:event-new-value>
48
+
49
+ # TextAreaField that conditionally appears and changes readonly state
50
+ - type: TextAreaField
51
+ dataLocation: ~~.formData.instruction
52
+ defaultFieldValue: ""
53
+ label: "Custom Instructions"
54
+ inputAttributes:
55
+ readonly: "readonly"
56
+ rows: 5
57
+ actions:
58
+ # Hide if prerequisite condition not met
59
+ - isEmpty: true
60
+ when: ~~.formData.sheet
61
+ what: hide
62
+ # Hide if a predefined option is selected (not empty and not custom)
63
+ - what: hide
64
+ when: ~~.formData.instructionType
65
+ isNot: ""
66
+ # Remove readonly when custom is selected (empty string)
67
+ - what: unsetAttribute
68
+ name: "readonly"
69
+ when: ~~.formData.instructionType
70
+ is: ""
71
+
72
+ data:
73
+ formData:
74
+ instructionType: "_"
75
+ instruction: ""
76
+ sheet: "ExampleSheet"
77
+ instructionOptions:
78
+ - label: "- Select an instruction -"
79
+ value: "_"
80
+ - label: "Predefined Option 1"
81
+ value: "This is a predefined instruction text for option 1"
82
+ - label: "Predefined Option 2"
83
+ value: "This is a predefined instruction text for option 2"
84
+ - label: "Custom Instruction"
85
+ value: ""
86
+ ```
87
+
88
+ ## How It Works
89
+
90
+ ### 1. Prerequisite Condition
91
+
92
+ Both fields check if `~~.formData.sheet` is not empty before appearing:
93
+
94
+ ```yaml
95
+ - isEmpty: true
96
+ when: ~~.formData.sheet
97
+ what: hide
98
+ ```
99
+
100
+ This ensures the fields only appear when the prerequisite data exists.
101
+
102
+ ### 2. Dual Data Update on SelectField Change
103
+
104
+ When the `SelectField` value changes, two `setData` actions execute:
105
+
106
+ 1. **Update dependent field**: Sets `~~.formData.instruction` to the new value (direct copy)
107
+ 2. **Update own field**: Sets `~~.formData.instructionType` to the new value
108
+
109
+ The `value` uses `<reactive-json:event-new-value>` which automatically extracts the selected value from the event.
110
+
111
+ **Important Note**: The second `setData` action updating `instructionType` is technically redundant since `SelectField` with `dataLocation` already updates its bound value automatically. However, it's included for explicitness and to ensure the value is set even if there are timing issues.
112
+
113
+ **Key Pattern**: The `SelectField` updates **two separate data paths** simultaneously:
114
+ - Its own bound value (`instructionType`) - for tracking which option was selected
115
+ - A dependent field's value (`instruction`) - for storing the actual instruction text
116
+
117
+ **Direct Value Copy**: Unlike patterns that use a mapping object (`instructionValues`), this pattern copies the selected value directly. This means:
118
+ - If a predefined option is selected: `instruction` receives the full instruction text from the option's `value`
119
+ - If `"_"` is selected: `instruction` receives `"_"`
120
+ - If `""` (custom) is selected: `instruction` receives `""`
121
+
122
+ This dual update pattern allows the `SelectField` to control both its own state and the state of a dependent field.
123
+
124
+ ### 3. Conditional Visibility of TextAreaField
125
+
126
+ The `TextAreaField` has two visibility conditions:
127
+
128
+ - **Prerequisite**: Hidden if `sheet` is empty
129
+ - **Selection-based**: Hidden if `instructionType` is not empty (meaning a predefined option was selected OR the empty placeholder `"_"` was selected)
130
+
131
+ ```yaml
132
+ - what: hide
133
+ when: ~~.formData.instructionType
134
+ isNot: ""
135
+ ```
136
+
137
+ This means the `TextAreaField` only appears when:
138
+ - `sheet` is selected (prerequisite met)
139
+ - AND `instructionType` is `""` (custom instruction selected)
140
+
141
+ **Important**: In this pattern:
142
+ - The empty placeholder "- Select an instruction -" has value `"_"` (underscore)
143
+ - The "custom" option has value `""` (empty string)
144
+ - Predefined options have their full instruction text as their `value`
145
+
146
+ This design allows distinguishing between "no selection" (`"_"`) and "custom selected" (`""`), while keeping the visibility logic simple: only show the TextAreaField when `instructionType` is exactly `""`.
147
+
148
+ ### 4. Dynamic Readonly State
149
+
150
+ The `TextAreaField` starts with `readonly: "readonly"` in `inputAttributes`. The readonly state is controlled by:
151
+
152
+ ```yaml
153
+ - what: unsetAttribute
154
+ name: "readonly"
155
+ when: ~~.formData.instructionType
156
+ is: ""
157
+ ```
158
+
159
+ **Behavior**: The readonly attribute is removed when `instructionType` is exactly `""`. Since "custom" has value `""` (empty string), selecting "custom" makes the field editable. The condition uses `is: ""` (exact match) rather than `isEmpty: true` to ensure it only triggers for the custom option, not for other empty states.
160
+
161
+ ## Data Flow Summary
162
+
163
+ 1. **User selects a predefined option** (Predefined Option 1 or Predefined Option 2):
164
+ - `instructionType` → Full instruction text (e.g., `"This is a predefined instruction text for option 1"`)
165
+ - `instruction` → Same full instruction text (direct copy from `value`)
166
+ - TextAreaField → Hidden (because `instructionType` is not empty)
167
+ - TextAreaField → Readonly (but hidden, so not relevant)
168
+
169
+ 2. **User selects "custom"** (Custom Instruction):
170
+ - `instructionType` → `""` (empty string - this is the key!)
171
+ - `instruction` → `""` (empty, ready for user input)
172
+ - TextAreaField → Visible (because `instructionType` is `""`)
173
+ - TextAreaField → Readonly removed (because `instructionType` is `""`)
174
+
175
+ 3. **User selects "- Select an instruction -"** (empty placeholder):
176
+ - `instructionType` → `"_"` (underscore)
177
+ - `instruction` → `"_"` (direct copy)
178
+ - TextAreaField → Hidden (because `instructionType` is not `""`)
179
+ - TextAreaField → Readonly (but hidden, so not relevant)
180
+
181
+ ## Key Takeaways
182
+
183
+ 1. **Dual Data Update**: A single `SelectField` can update multiple data paths using multiple `setData` actions
184
+ 2. **Conditional Visibility**: Fields can be hidden based on prerequisite conditions AND selection state
185
+ 3. **Dynamic Attributes**: Field attributes (like `readonly`) can be dynamically controlled based on data state
186
+ 4. **Event Value Placeholder**: Use `<reactive-json:event-new-value>` to automatically extract the new value from the event
187
+
188
+ ## Design Decision: Value Structure
189
+
190
+ In this pattern, values are structured to distinguish three states:
191
+
192
+ - **`"_"` (underscore)** = Empty placeholder ("- Select an instruction -") - TextAreaField hidden
193
+ - **`""` (empty string)** = Custom input mode ("Custom Instruction") - TextAreaField visible and editable
194
+ - **Full instruction text** = Predefined option selected - TextAreaField hidden
195
+
196
+ **Key Design Choices**:
197
+
198
+ 1. **Values stored directly in options**: Full instruction texts are stored directly in the `value` property of each option in `instructionOptions`, eliminating the need for a separate `instructionValues` mapping object.
199
+
200
+ 2. **Direct value copy**: The `SelectField` copies the selected value directly to `instruction` using `<reactive-json:event-new-value>`, without conditional logic. This means:
201
+ - Selecting a predefined option copies the full instruction text
202
+ - Selecting `"_"` copies `"_"`
203
+ - Selecting `""` copies `""`
204
+
205
+ 3. **Simple visibility logic**: The TextAreaField visibility uses `isNot: ""` which hides it for both `"_"` and predefined options, showing it only for `""` (custom).
206
+
207
+ 4. **Readonly condition**: Uses `is: ""` (exact match) rather than `isEmpty: true` to ensure it only triggers for the custom option.
208
+
209
+ This design allows clear distinction between all three states while keeping the implementation simple and maintainable.
@@ -0,0 +1,74 @@
1
+ renderView:
2
+ - type: Markdown
3
+ content: |
4
+ # Conditional Field with Dual Data Update Pattern
5
+
6
+ This example demonstrates a pattern where a `SelectField` controls both its own value and another field's value, while a `TextAreaField` conditionally appears and changes its `readonly` state based on the selection.
7
+
8
+ - type: RjBuildDescriber
9
+ title: "Dual Update Pattern"
10
+ description: "SelectField updates two data paths, TextAreaField conditionally appears"
11
+ toDescribe:
12
+ renderView:
13
+ # SelectField that controls both its value and another field
14
+ - type: SelectField
15
+ dataLocation: ~~.formData.instructionType
16
+ defaultFieldValue: "_"
17
+ dynamicOptions: ~~.instructionOptions
18
+ label: "Instructions"
19
+ actions:
20
+ # Hide if prerequisite condition not met
21
+ - isEmpty: true
22
+ when: ~~.formData.sheet
23
+ what: hide
24
+ # Update the dependent field's value (direct copy)
25
+ - what: setData
26
+ on: change
27
+ path: ~~.formData.instruction
28
+ value: <reactive-json:event-new-value>
29
+ # Update its own value (redundant but explicit)
30
+ - what: setData
31
+ on: change
32
+ path: ~~.formData.instructionType
33
+ value: <reactive-json:event-new-value>
34
+
35
+ # TextAreaField that conditionally appears and changes readonly state
36
+ - type: TextAreaField
37
+ dataLocation: ~~.formData.instruction
38
+ defaultFieldValue: ""
39
+ label: "Custom Instructions"
40
+ inputAttributes:
41
+ readonly: "readonly"
42
+ rows: 5
43
+ actions:
44
+ # Hide if prerequisite condition not met
45
+ - isEmpty: true
46
+ when: ~~.formData.sheet
47
+ what: hide
48
+ # Hide if a predefined option is selected (not empty and not custom)
49
+ - what: hide
50
+ when: ~~.formData.instructionType
51
+ isNot: ""
52
+ # Remove readonly when custom is selected (empty string)
53
+ - what: unsetAttribute
54
+ name: "readonly"
55
+ when: ~~.formData.instructionType
56
+ is: ""
57
+
58
+ data:
59
+ formData:
60
+ instructionType: "_"
61
+ instruction: ""
62
+ sheet: "ExampleSheet"
63
+ instructionOptions:
64
+ - label: "- Select an instruction -"
65
+ value: "_"
66
+ - label: "Predefined Option 1"
67
+ value: "This is a predefined instruction text for option 1"
68
+ - label: "Predefined Option 2"
69
+ value: "This is a predefined instruction text for option 2"
70
+ - label: "Custom Instruction"
71
+ value: ""
72
+
73
+ templates:
74
+