@ea-lab/reactive-json-docs 2.8.0 → 2.11.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 +142 -18
- package/public/rjbuild/docs/core/element/form/CheckBoxField.yaml +132 -7
- package/public/rjbuild/docs/core/element/form/SelectField.md +36 -10
- package/public/rjbuild/docs/core/element/form/SelectField.yaml +37 -3
- package/public/rjbuild/docs/core/element/form/formElementsCommon.md +32 -0
- package/public/rjbuild/docs/core/element/html/Html.yaml +47 -0
- package/public/rjbuild/docs/core/element/html/LabelFromValue.md +159 -0
- package/public/rjbuild/docs/core/element/html/LabelFromValue.yaml +163 -10
- package/public/rjbuild/docs/core/element/special/DataSync.md +41 -1
- package/public/rjbuild/docs/core/element/special/DataSync.yaml +41 -1
- package/public/rjbuild/docs/core/example/native-html-forms.md +19 -2
- package/public/rjbuild/docs/core/hook/index.md +3 -0
- package/public/rjbuild/docs/core/hook/index.yaml +3 -0
- package/public/rjbuild/docs/core/reaction/collectField.md +51 -0
- package/public/rjbuild/docs/core/reaction/collectField.yaml +81 -0
- package/public/rjbuild/docs/core/reaction/fetchData.md +21 -1
- package/public/rjbuild/docs/core/reaction/fetchData.yaml +2 -2
- package/public/rjbuild/docs/core/reaction/index.md +5 -0
- package/public/rjbuild/docs/core/reaction/index.yaml +5 -0
- package/public/rjbuild/docs/core/reaction/joinData.md +51 -0
- package/public/rjbuild/docs/core/reaction/joinData.yaml +87 -0
- package/public/rjbuild/docs/core/reaction/printPage.md +22 -0
- package/public/rjbuild/docs/core/reaction/printPage.yaml +29 -0
- package/public/rjbuild/docs/core/reaction/redirectNow.md +20 -2
- package/public/rjbuild/docs/core/reaction/redirectNow.yaml +24 -3
- package/public/rjbuild/docs/core/reaction/setClipboardData.md +35 -6
- package/public/rjbuild/docs/core/reaction/setClipboardData.yaml +18 -6
- package/public/rjbuild/docs/core/reaction/stringifyData.md +45 -0
- package/public/rjbuild/docs/core/reaction/stringifyData.yaml +58 -0
- package/public/rjbuild/docs/core/reaction/submitData.md +1 -1
- package/public/rjbuild/docs/core/reaction/submitData.yaml +4 -2
- package/public/rjbuild/docs/core/reaction/toggleData.md +72 -0
- package/public/rjbuild/docs/core/reaction/toggleData.yaml +77 -0
- package/public/rjbuild/docs/getting-started/reactions.md +5 -0
- package/public/rjbuild/docs/getting-started/reactions.yaml +5 -0
- package/public/rjbuild/docs/getting-started/rjbuild-structure.md +23 -1
- package/public/rjbuild/docs/getting-started/rjbuild-structure.yaml +25 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ea-lab/reactive-json-docs",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.11.0",
|
|
4
4
|
"description": "Complete documentation for Reactive-JSON - Components, examples and LLM-parsable guides",
|
|
5
5
|
"main": "public/rjbuild/docs/index.yaml",
|
|
6
6
|
"files": [
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"private": false,
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@craco/craco": "^7.1.0",
|
|
29
|
-
"@ea-lab/reactive-json": "^2.
|
|
29
|
+
"@ea-lab/reactive-json": "^2.11.1",
|
|
30
30
|
"@ea-lab/reactive-json-chartjs": "^1.1.1",
|
|
31
31
|
"@npmcli/fs": "^4.0.0",
|
|
32
32
|
"@reduxjs/toolkit": "^2.6.1",
|
|
@@ -24,14 +24,15 @@ The `CheckBoxField` component provides checkbox and radio button groups with aut
|
|
|
24
24
|
- `label` (string or View props, optional): Field label text (supports template evaluation and View component rendering).
|
|
25
25
|
- `options` (array, optional): Static array of option objects, each with:
|
|
26
26
|
- `label` (string, optional): Display text for the option (supports template evaluation).
|
|
27
|
-
- `value` (any, required): Value stored when this option is selected.
|
|
27
|
+
- `value` (any, required): Value stored when this option is selected (supports template evaluation, like `label`).
|
|
28
28
|
- `attributes` (object, optional): Attributes applied to the option's container div.
|
|
29
|
-
- `dynamicOptions` (string, optional): Template path to dynamic options array (e.g., `~.availableItems`). Takes precedence over `options` if both are provided.
|
|
29
|
+
- `dynamicOptions` (string, optional): Template path to dynamic options array (e.g., `~.availableItems`). Takes precedence over `options` if both are provided. The items can be `{label, value}` objects, scalars (each scalar is used as both label and value), or objects of any shape mapped with `optionMapping`.
|
|
30
|
+
- `optionMapping` (object, optional): Builds each option from an item of the options list. It is evaluated once per item, **with the item as the template context**: `~.title` reads the item's `title`, `~` is the whole item, `~~.` still reads the global data. The mapped keys (`label`, `value`, `attributes`) override the item's keys. See [Data-driven checkbox lists](#data-driven-checkbox-lists).
|
|
30
31
|
- `controlType` (string, optional): Type of control - `"checkbox"` (default) or `"radio"`.
|
|
31
|
-
- `multiple` (boolean, optional): Whether multiple selections are allowed. Defaults to `true`
|
|
32
|
+
- `multiple` (boolean, optional): Whether multiple selections are allowed. Defaults to `true` when the bound data is an array or when more than one option exists, `false` otherwise. For radio buttons, this is automatically `false`.
|
|
32
33
|
- `attributes` (object, optional): Attributes applied to the wrapper div (or container div if no wrapper).
|
|
33
34
|
- `inputAttributes` (object, optional): Attributes applied directly to each input element.
|
|
34
|
-
- `labelAttributes` (object, optional): Attributes applied to the
|
|
35
|
+
- `labelAttributes` (object, optional): Attributes applied to the field label and to each option label (`htmlFor` is automatically managed). An `id` is only applied to the field label.
|
|
35
36
|
- `forceWrapper` (boolean, optional): Forces the presence (true) or absence (false) of the wrapper div. If omitted, wrapper is automatic only if label is present.
|
|
36
37
|
- `actions` (array, optional): Actions to execute based on field state.
|
|
37
38
|
|
|
@@ -43,6 +44,8 @@ The component automatically synchronizes its value with the global data context.
|
|
|
43
44
|
- **Single checkbox**: Stores a boolean (`true`) or the option's value when checked, `false` when unchecked.
|
|
44
45
|
- **Multiple checkboxes**: Stores an array of selected option values.
|
|
45
46
|
|
|
47
|
+
The mode is chosen as follows: radio when `controlType: "radio"`; otherwise `multiple` when set; otherwise **multiple when the bound data is already an array** or when there is more than one option. Initializing the data as an array (`[]`) is therefore enough to get a list of values, even with a single option.
|
|
48
|
+
|
|
46
49
|
When `dataLocation` is used, the value is stored at the specified path. Without `dataLocation`, the value is stored in the template context using the component's `datafield`.
|
|
47
50
|
|
|
48
51
|
## Selection Modes
|
|
@@ -69,7 +72,7 @@ Radio buttons allow only one selection at a time. Set `controlType: "radio"`:
|
|
|
69
72
|
|
|
70
73
|
### Single Checkbox
|
|
71
74
|
|
|
72
|
-
A single checkbox stores a boolean or the option's value:
|
|
75
|
+
A single checkbox (one option, data not initialized as an array) stores a boolean or the option's value:
|
|
73
76
|
|
|
74
77
|
```yaml
|
|
75
78
|
- type: CheckBoxField
|
|
@@ -83,6 +86,8 @@ A single checkbox stores a boolean or the option's value:
|
|
|
83
86
|
|
|
84
87
|
**Data stored**: `true` when checked, `false` when unchecked (or the option's value if different from `true`)
|
|
85
88
|
|
|
89
|
+
Several single checkboxes bound to the same data location overwrite each other's value, so they check and uncheck together. When they have different values, the component logs a warning: initialize the data as an array, or set `multiple: true`.
|
|
90
|
+
|
|
86
91
|
### Multiple Checkboxes
|
|
87
92
|
|
|
88
93
|
Multiple checkboxes allow selecting several options simultaneously:
|
|
@@ -118,17 +123,15 @@ You can override the default behavior using the `forceWrapper` property. Setting
|
|
|
118
123
|
|
|
119
124
|
**With label (automatic wrapper):**
|
|
120
125
|
```html
|
|
121
|
-
<div>
|
|
122
|
-
<label>Select options:</label>
|
|
126
|
+
<div role="group" aria-labelledby="checkbox-abc123-label">
|
|
127
|
+
<label id="checkbox-abc123-label">Select options:</label>
|
|
123
128
|
<div>
|
|
124
|
-
<
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
<
|
|
129
|
-
|
|
130
|
-
<label htmlFor="checkbox-abc123-1">Option 2</label>
|
|
131
|
-
</div>
|
|
129
|
+
<input type="checkbox" id="checkbox-abc123-0" value="opt1" />
|
|
130
|
+
<label for="checkbox-abc123-0">Option 1</label>
|
|
131
|
+
</div>
|
|
132
|
+
<div>
|
|
133
|
+
<input type="checkbox" id="checkbox-abc123-1" value="opt2" />
|
|
134
|
+
<label for="checkbox-abc123-1">Option 2</label>
|
|
132
135
|
</div>
|
|
133
136
|
</div>
|
|
134
137
|
```
|
|
@@ -138,7 +141,7 @@ You can override the default behavior using the `forceWrapper` property. Setting
|
|
|
138
141
|
<div>
|
|
139
142
|
<div>
|
|
140
143
|
<input type="checkbox" id="checkbox-xyz789-0" value="opt1" />
|
|
141
|
-
<label
|
|
144
|
+
<label for="checkbox-xyz789-0">Option 1</label>
|
|
142
145
|
</div>
|
|
143
146
|
</div>
|
|
144
147
|
```
|
|
@@ -186,6 +189,102 @@ Each option can have its own attributes applied to its container div:
|
|
|
186
189
|
|
|
187
190
|
The component automatically generates unique IDs for each checkbox/radio button. If you provide an `id` in `inputAttributes`, it will be used as the base ID, and each option will have an index appended (e.g., `"my-id-0"`, `"my-id-1"`).
|
|
188
191
|
|
|
192
|
+
## Accessibility
|
|
193
|
+
|
|
194
|
+
- Each option label is associated with its input (`for` / `id`).
|
|
195
|
+
- When a field `label` names several options, the element containing the options gets `role="group"` and `aria-labelledby` pointing to the field label (id from `labelAttributes.id`, or `<base id>-label`). Assistive technologies announce the field label when entering the group.
|
|
196
|
+
- When a field `label` comes with a single option without its own label, the field label is directly associated with the input.
|
|
197
|
+
- The radios of a field share a `name` (the base ID), so they form a native radio group: one tab stop, arrow keys navigation. Set `inputAttributes.name` to group radios rendered by several fields (one per `Switch` item, for example).
|
|
198
|
+
- `attributes` can override `role` and `aria-labelledby`.
|
|
199
|
+
|
|
200
|
+
## Data-driven checkbox lists
|
|
201
|
+
|
|
202
|
+
To let users check items of a list held in the data (sessions, tags, recipients...), prefer, in this order:
|
|
203
|
+
|
|
204
|
+
### 1. One field fed by the list (recommended)
|
|
205
|
+
|
|
206
|
+
Use `dynamicOptions` on the list and `optionMapping` to read the keys of the items. The items can have any shape: here, a list of `{label}` objects typed by an editor.
|
|
207
|
+
|
|
208
|
+
```yaml
|
|
209
|
+
renderView:
|
|
210
|
+
- type: CheckBoxField
|
|
211
|
+
dataLocation: ~~.lead.sessions
|
|
212
|
+
label: "Sessions"
|
|
213
|
+
dynamicOptions: ~~.sessions
|
|
214
|
+
optionMapping:
|
|
215
|
+
label: ~.label
|
|
216
|
+
value: ~.label
|
|
217
|
+
|
|
218
|
+
data:
|
|
219
|
+
sessions:
|
|
220
|
+
- label: "20 octobre"
|
|
221
|
+
- label: "17 novembre"
|
|
222
|
+
- label: "15 décembre"
|
|
223
|
+
lead:
|
|
224
|
+
sessions: []
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Checking "17 novembre" then "20 octobre" stores `lead.sessions: ["17 novembre", "20 octobre"]`. The options are a labelled group for assistive technologies. With a list of scalars (`sessions: ["20 octobre", "17 novembre"]`), `optionMapping` is not needed: each scalar is both the label and the value.
|
|
228
|
+
|
|
229
|
+
### 2. One field per Switch item
|
|
230
|
+
|
|
231
|
+
When each item needs its own markup around the checkbox, render one single-option field per item. The option `value` is evaluated in the item context, and the data initialized as an array keeps the fields independent:
|
|
232
|
+
|
|
233
|
+
```yaml
|
|
234
|
+
renderView:
|
|
235
|
+
- type: Switch
|
|
236
|
+
content: ~~.sessions
|
|
237
|
+
singleOption:
|
|
238
|
+
load: sessionItem
|
|
239
|
+
|
|
240
|
+
templates:
|
|
241
|
+
sessionItem:
|
|
242
|
+
- type: CheckBoxField
|
|
243
|
+
dataLocation: ~~.lead.sessions
|
|
244
|
+
options:
|
|
245
|
+
- label: ~.label
|
|
246
|
+
value: ~.label
|
|
247
|
+
|
|
248
|
+
data:
|
|
249
|
+
sessions:
|
|
250
|
+
- label: "20 octobre"
|
|
251
|
+
- label: "17 novembre"
|
|
252
|
+
lead:
|
|
253
|
+
sessions: []
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Keep `lead.sessions: []` in the data (or set `multiple: true` on the field): without an array, each field is a single checkbox that overwrites the shared value, and a warning is logged. For a single choice, use `controlType: radio` with a shared `inputAttributes.name`; the data then holds the selected value.
|
|
257
|
+
|
|
258
|
+
### 3. Raw `input` elements (last resort)
|
|
259
|
+
|
|
260
|
+
A raw `type: input` checkbox is a controlled input: its `checked` attribute must be bound, otherwise it is forced to `false` and never shows as checked (a warning is logged when it has event reactions). Bind a boolean with `checked: ~.isSelected`, or the membership in a list with an attribute transform:
|
|
261
|
+
|
|
262
|
+
```yaml
|
|
263
|
+
- type: input
|
|
264
|
+
attributes:
|
|
265
|
+
type: checkbox
|
|
266
|
+
value: ~.label
|
|
267
|
+
attributeTransforms:
|
|
268
|
+
- what: setAttributeValue
|
|
269
|
+
name: checked
|
|
270
|
+
mode: replace
|
|
271
|
+
value: true
|
|
272
|
+
when: ~~.lead.sessions
|
|
273
|
+
contains: ~.label
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
To store the list of checked values, add a [toggleData](../../reaction/toggleData.md) reaction: it adds the value when absent, and removes it when present.
|
|
277
|
+
|
|
278
|
+
```yaml
|
|
279
|
+
actions:
|
|
280
|
+
- what: toggleData
|
|
281
|
+
on: change
|
|
282
|
+
path: ~~.lead.sessions
|
|
283
|
+
value: ~.label
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Prefer patterns 1 and 2, which also handle the labels and the accessibility of the group.
|
|
287
|
+
|
|
189
288
|
## Empty Options Handling
|
|
190
289
|
|
|
191
290
|
If `options` is empty or not an array, the component returns `null` and renders nothing. This is useful for conditional rendering scenarios.
|
|
@@ -297,6 +396,31 @@ data:
|
|
|
297
396
|
selectedItems: []
|
|
298
397
|
```
|
|
299
398
|
|
|
399
|
+
### Dynamic Options with a Mapping
|
|
400
|
+
|
|
401
|
+
```yaml
|
|
402
|
+
renderView:
|
|
403
|
+
- type: CheckBoxField
|
|
404
|
+
dataLocation: ~.recipients
|
|
405
|
+
label: "Recipients:"
|
|
406
|
+
dynamicOptions: ~.users
|
|
407
|
+
optionMapping:
|
|
408
|
+
label: ~.displayName
|
|
409
|
+
value: ~.uid
|
|
410
|
+
attributes:
|
|
411
|
+
class: ~.role
|
|
412
|
+
|
|
413
|
+
data:
|
|
414
|
+
users:
|
|
415
|
+
- uid: 12
|
|
416
|
+
displayName: "Ada Lovelace"
|
|
417
|
+
role: "admin"
|
|
418
|
+
- uid: 27
|
|
419
|
+
displayName: "Alan Turing"
|
|
420
|
+
role: "editor"
|
|
421
|
+
recipients: []
|
|
422
|
+
```
|
|
423
|
+
|
|
300
424
|
### With Actions
|
|
301
425
|
|
|
302
426
|
```yaml
|
|
@@ -347,11 +471,11 @@ data:
|
|
|
347
471
|
|
|
348
472
|
- **Flexible selection modes**: Supports radio buttons, single checkbox, and multiple checkboxes
|
|
349
473
|
- **Automatic data synchronization**: Values are automatically stored in the correct format
|
|
350
|
-
- **Dynamic options**: Options can be provided via template evaluation using `dynamicOptions`
|
|
474
|
+
- **Dynamic options**: Options can be provided via template evaluation using `dynamicOptions`, from a list of any shape with `optionMapping`
|
|
351
475
|
- **Per-option customization**: Each option can have its own attributes
|
|
352
476
|
- **Label flexibility**: Supports both simple strings and View component rendering
|
|
353
477
|
- **Wrapper control**: Flexible wrapper system for styling control
|
|
354
|
-
- **Accessibility**: Automatic label association
|
|
478
|
+
- **Accessibility**: Automatic label association, labelled group of options, native radio groups
|
|
355
479
|
- **Empty state handling**: Gracefully handles empty options
|
|
356
480
|
|
|
357
481
|
## Limitations
|
|
@@ -46,14 +46,20 @@ renderView:
|
|
|
46
46
|
content: |
|
|
47
47
|
Static array of option objects, each with:
|
|
48
48
|
- `label` (string, optional): Display text for the option (supports template evaluation)
|
|
49
|
-
- `value` (any, required): Value stored when this option is selected
|
|
49
|
+
- `value` (any, required): Value stored when this option is selected (supports template evaluation, like `label`)
|
|
50
50
|
- `attributes` (object, optional): Attributes applied to the option's container div
|
|
51
51
|
- term:
|
|
52
52
|
code: dynamicOptions
|
|
53
53
|
after: "(string, optional)"
|
|
54
54
|
details:
|
|
55
55
|
type: Markdown
|
|
56
|
-
content: "Template path to dynamic options array (e.g., `~.availableItems`). Takes precedence over `options` if both are provided."
|
|
56
|
+
content: "Template path to dynamic options array (e.g., `~.availableItems`). Takes precedence over `options` if both are provided. The items can be `{label, value}` objects, scalars (each scalar is used as both label and value), or objects of any shape mapped with `optionMapping`."
|
|
57
|
+
- term:
|
|
58
|
+
code: optionMapping
|
|
59
|
+
after: "(object, optional)"
|
|
60
|
+
details:
|
|
61
|
+
type: Markdown
|
|
62
|
+
content: "Builds each option from an item of the options list. It is evaluated once per item, **with the item as the template context**: `~.title` reads the item's `title`, `~` is the whole item, `~~.` still reads the global data. The mapped keys (`label`, `value`, `attributes`) override the item's keys. See *Data-driven checkbox lists* below."
|
|
57
63
|
- term:
|
|
58
64
|
code: controlType
|
|
59
65
|
after: "(string, optional)"
|
|
@@ -61,7 +67,7 @@ renderView:
|
|
|
61
67
|
- term:
|
|
62
68
|
code: multiple
|
|
63
69
|
after: "(boolean, optional)"
|
|
64
|
-
details: "Whether multiple selections are allowed. Defaults to `true`
|
|
70
|
+
details: "Whether multiple selections are allowed. Defaults to `true` when the bound data is an array or when more than one option exists, `false` otherwise. For radio buttons, this is automatically `false`."
|
|
65
71
|
- term:
|
|
66
72
|
code: attributes
|
|
67
73
|
after: "(object, optional)"
|
|
@@ -73,7 +79,7 @@ renderView:
|
|
|
73
79
|
- term:
|
|
74
80
|
code: labelAttributes
|
|
75
81
|
after: "(object, optional)"
|
|
76
|
-
details: "Attributes applied to the
|
|
82
|
+
details: "Attributes applied to the field label and to each option label (`htmlFor` is automatically managed). An `id` is only applied to the field label."
|
|
77
83
|
- term:
|
|
78
84
|
code: forceWrapper
|
|
79
85
|
after: "(boolean, optional)"
|
|
@@ -93,6 +99,8 @@ renderView:
|
|
|
93
99
|
- **Single checkbox**: Stores a boolean (`true`) or the option's value when checked, `false` when unchecked
|
|
94
100
|
- **Multiple checkboxes**: Stores an array of selected option values
|
|
95
101
|
|
|
102
|
+
The mode is chosen as follows: radio when `controlType: "radio"`; otherwise `multiple` when set; otherwise **multiple when the bound data is already an array** or when there is more than one option. Initializing the data as an array (`[]`) is therefore enough to get a list of values, even with a single option.
|
|
103
|
+
|
|
96
104
|
When `dataLocation` is used, the value is stored at the specified path. Without `dataLocation`, the value is stored in the template context using the component's `datafield`.
|
|
97
105
|
|
|
98
106
|
## Selection Modes
|
|
@@ -105,10 +113,12 @@ renderView:
|
|
|
105
113
|
|
|
106
114
|
### Single Checkbox
|
|
107
115
|
|
|
108
|
-
A single checkbox stores a boolean or the option's value:
|
|
116
|
+
A single checkbox (one option, data not initialized as an array) stores a boolean or the option's value:
|
|
109
117
|
|
|
110
118
|
**Data stored**: `true` when checked, `false` when unchecked (or the option's value if different from `true`)
|
|
111
119
|
|
|
120
|
+
Several single checkboxes bound to the same data location overwrite each other's value, so they check and uncheck together. When they have different values, the component logs a warning: initialize the data as an array, or set `multiple: true`.
|
|
121
|
+
|
|
112
122
|
### Multiple Checkboxes
|
|
113
123
|
|
|
114
124
|
Multiple checkboxes allow selecting several options simultaneously:
|
|
@@ -195,6 +205,121 @@ renderView:
|
|
|
195
205
|
value: "item4"
|
|
196
206
|
selectedItems: []
|
|
197
207
|
|
|
208
|
+
- type: Markdown
|
|
209
|
+
content: |
|
|
210
|
+
## Accessibility
|
|
211
|
+
|
|
212
|
+
- Each option label is associated with its input (`for` / `id`).
|
|
213
|
+
- When a field `label` names several options, the element containing the options gets `role="group"` and `aria-labelledby` pointing to the field label (id from `labelAttributes.id`, or `<base id>-label`). Assistive technologies announce the field label when entering the group.
|
|
214
|
+
- When a field `label` comes with a single option without its own label, the field label is directly associated with the input.
|
|
215
|
+
- The radios of a field share a `name` (the base ID), so they form a native radio group: one tab stop, arrow keys navigation. Set `inputAttributes.name` to group radios rendered by several fields (one per `Switch` item, for example).
|
|
216
|
+
- `attributes` can override `role` and `aria-labelledby`.
|
|
217
|
+
|
|
218
|
+
## Data-driven checkbox lists
|
|
219
|
+
|
|
220
|
+
To let users check items of a list held in the data (sessions, tags, recipients...), prefer, in this order:
|
|
221
|
+
|
|
222
|
+
### 1. One field fed by the list (recommended)
|
|
223
|
+
|
|
224
|
+
Use `dynamicOptions` on the list and `optionMapping` to read the keys of the items. The items can have any shape: here, a list of `{label}` objects typed by an editor. With a list of scalars, `optionMapping` is not needed: each scalar is both the label and the value.
|
|
225
|
+
|
|
226
|
+
- type: RjBuildDescriber
|
|
227
|
+
title: "One field fed by the list"
|
|
228
|
+
description: "dynamicOptions + optionMapping: the items only have a label, which is also the stored value"
|
|
229
|
+
toDescribe:
|
|
230
|
+
renderView:
|
|
231
|
+
- type: CheckBoxField
|
|
232
|
+
dataLocation: ~~.lead.sessions
|
|
233
|
+
label: "Sessions"
|
|
234
|
+
dynamicOptions: ~~.sessions
|
|
235
|
+
optionMapping:
|
|
236
|
+
label: ~.label
|
|
237
|
+
value: ~.label
|
|
238
|
+
- type: div
|
|
239
|
+
content:
|
|
240
|
+
- type: strong
|
|
241
|
+
content: "Selected: "
|
|
242
|
+
- type: Join
|
|
243
|
+
content: ~~.lead.sessions
|
|
244
|
+
separator: ", "
|
|
245
|
+
data:
|
|
246
|
+
sessions:
|
|
247
|
+
- label: "20 octobre"
|
|
248
|
+
- label: "17 novembre"
|
|
249
|
+
- label: "15 décembre"
|
|
250
|
+
lead:
|
|
251
|
+
sessions: []
|
|
252
|
+
|
|
253
|
+
- type: Markdown
|
|
254
|
+
content: |
|
|
255
|
+
### 2. One field per Switch item
|
|
256
|
+
|
|
257
|
+
When each item needs its own markup around the checkbox, render one single-option field per item. The option `value` is evaluated in the item context, and the data initialized as an array keeps the fields independent.
|
|
258
|
+
|
|
259
|
+
Keep `lead.sessions: []` in the data (or set `multiple: true` on the field): without an array, each field is a single checkbox that overwrites the shared value, and a warning is logged. For a single choice, use `controlType: radio` with a shared `inputAttributes.name`; the data then holds the selected value.
|
|
260
|
+
|
|
261
|
+
- type: RjBuildDescriber
|
|
262
|
+
title: "One field per Switch item"
|
|
263
|
+
description: "Each item renders its own single-option CheckBoxField, all bound to the same array"
|
|
264
|
+
toDescribe:
|
|
265
|
+
renderView:
|
|
266
|
+
- type: Switch
|
|
267
|
+
content: ~~.sessions
|
|
268
|
+
singleOption:
|
|
269
|
+
load: sessionItem
|
|
270
|
+
- type: div
|
|
271
|
+
content:
|
|
272
|
+
- type: strong
|
|
273
|
+
content: "Selected: "
|
|
274
|
+
- type: Join
|
|
275
|
+
content: ~~.lead.sessions
|
|
276
|
+
separator: ", "
|
|
277
|
+
templates:
|
|
278
|
+
sessionItem:
|
|
279
|
+
- type: CheckBoxField
|
|
280
|
+
dataLocation: ~~.lead.sessions
|
|
281
|
+
options:
|
|
282
|
+
- label: ~.label
|
|
283
|
+
value: ~.label
|
|
284
|
+
data:
|
|
285
|
+
sessions:
|
|
286
|
+
- label: "20 octobre"
|
|
287
|
+
- label: "17 novembre"
|
|
288
|
+
- label: "15 décembre"
|
|
289
|
+
lead:
|
|
290
|
+
sessions: []
|
|
291
|
+
|
|
292
|
+
- type: Markdown
|
|
293
|
+
content: |
|
|
294
|
+
### 3. Raw `input` elements (last resort)
|
|
295
|
+
|
|
296
|
+
A raw `type: input` checkbox is a controlled input: its `checked` attribute must be bound, otherwise it is forced to `false` and never shows as checked (a warning is logged when it has event reactions). Bind a boolean with `checked: ~.isSelected`, or the membership in a list with an attribute transform:
|
|
297
|
+
|
|
298
|
+
```yaml
|
|
299
|
+
- type: input
|
|
300
|
+
attributes:
|
|
301
|
+
type: checkbox
|
|
302
|
+
value: ~.label
|
|
303
|
+
attributeTransforms:
|
|
304
|
+
- what: setAttributeValue
|
|
305
|
+
name: checked
|
|
306
|
+
mode: replace
|
|
307
|
+
value: true
|
|
308
|
+
when: ~~.lead.sessions
|
|
309
|
+
contains: ~.label
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
To store the list of checked values, add a [toggleData](../../reaction/toggleData) reaction: it adds the value when absent, and removes it when present.
|
|
313
|
+
|
|
314
|
+
```yaml
|
|
315
|
+
actions:
|
|
316
|
+
- what: toggleData
|
|
317
|
+
on: change
|
|
318
|
+
path: ~~.lead.sessions
|
|
319
|
+
value: ~.label
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
Prefer patterns 1 and 2, which also handle the labels and the accessibility of the group.
|
|
198
323
|
|
|
199
324
|
- type: Markdown
|
|
200
325
|
content: |
|
|
@@ -202,11 +327,11 @@ renderView:
|
|
|
202
327
|
|
|
203
328
|
- **Flexible selection modes**: Supports radio buttons, single checkbox, and multiple checkboxes
|
|
204
329
|
- **Automatic data synchronization**: Values are automatically stored in the correct format
|
|
205
|
-
- **Dynamic options**: Options can be provided via template evaluation using `dynamicOptions`
|
|
330
|
+
- **Dynamic options**: Options can be provided via template evaluation using `dynamicOptions`, from a list of any shape with `optionMapping`
|
|
206
331
|
- **Per-option customization**: Each option can have its own attributes
|
|
207
332
|
- **Label flexibility**: Supports both simple strings and View component rendering
|
|
208
333
|
- **Wrapper control**: Flexible wrapper system for styling control
|
|
209
|
-
- **Accessibility**: Automatic label association
|
|
334
|
+
- **Accessibility**: Automatic label association, labelled group of options, native radio groups
|
|
210
335
|
- **Empty state handling**: Gracefully handles empty options
|
|
211
336
|
|
|
212
337
|
## Limitations
|
|
@@ -22,8 +22,9 @@ The `SelectField` component provides a native HTML select dropdown with automati
|
|
|
22
22
|
- `dataLocation` (string, optional): Path to bind the field value in the data context.
|
|
23
23
|
- `defaultFieldValue` (any, optional): Default value when no data is present.
|
|
24
24
|
- `label` (string or View props, optional): Field label text (supports template evaluation and View component rendering).
|
|
25
|
-
- `options` (array, optional): Static array of option objects with `label` and `value` properties.
|
|
26
|
-
- `dynamicOptions` (string, optional): Template path to dynamic options array (e.g., `~.availableCategories`). Takes precedence over `options` if both are provided.
|
|
25
|
+
- `options` (array, optional): Static array of option objects with `label` and `value` properties (both support template evaluation).
|
|
26
|
+
- `dynamicOptions` (string, optional): Template path to dynamic options array (e.g., `~.availableCategories`). Takes precedence over `options` if both are provided. The items can be `{label, value}` objects, scalars (each scalar is used as both label and value), or objects of any shape mapped with `optionMapping`.
|
|
27
|
+
- `optionMapping` (object, optional): Builds each option from an item of the options list. It is evaluated once per item, **with the item as the template context**: `~.title` reads the item's `title`, `~` is the whole item, `~~.` still reads the global data. The mapped keys (`label`, `value`) override the item's keys.
|
|
27
28
|
- `allowEmptyStringAsValue` (boolean, optional): Preserve empty strings as `""` instead of converting to `undefined` (default: `false`).
|
|
28
29
|
- `attributes` (object, optional): Attributes applied to the container div (or merged with inputAttributes if no wrapper).
|
|
29
30
|
- `inputAttributes` (object, optional): Attributes applied directly to the select element.
|
|
@@ -109,20 +110,22 @@ The `label` property supports both simple strings and View component rendering,
|
|
|
109
110
|
dynamicOptions: ~.categories
|
|
110
111
|
```
|
|
111
112
|
|
|
112
|
-
## Option Labels
|
|
113
|
+
## Option Labels and Values
|
|
113
114
|
|
|
114
|
-
|
|
115
|
+
The `label` and the `value` of each option support template evaluation: a string that is a whole template reference (`~.key`, `~~.key`, `~>key`...) is replaced by the referenced data. Text around a reference is not interpolated (`"Item: ~.itemName"` is displayed as is).
|
|
115
116
|
|
|
116
117
|
```yaml
|
|
117
118
|
- type: SelectField
|
|
118
|
-
dataLocation: ~.
|
|
119
|
+
dataLocation: ~.owner
|
|
119
120
|
options:
|
|
120
|
-
- label: "
|
|
121
|
-
value: "
|
|
122
|
-
- label:
|
|
123
|
-
value:
|
|
121
|
+
- label: "Nobody"
|
|
122
|
+
value: ""
|
|
123
|
+
- label: ~~.currentUser.name
|
|
124
|
+
value: ~~.currentUser.id
|
|
124
125
|
```
|
|
125
126
|
|
|
127
|
+
Inside a template (a `Switch` item, for example), `~.` reads the item data, so each item can offer its own option.
|
|
128
|
+
|
|
126
129
|
## Empty Options Handling
|
|
127
130
|
|
|
128
131
|
If `options` is empty or not an array, the component displays a single option: "No options available". This is useful for conditional rendering scenarios where options may be loaded dynamically.
|
|
@@ -211,6 +214,29 @@ data:
|
|
|
211
214
|
selectedCategory: ""
|
|
212
215
|
```
|
|
213
216
|
|
|
217
|
+
### Dynamic Options with a Mapping
|
|
218
|
+
|
|
219
|
+
Use `optionMapping` when the items of the list do not have `label` / `value` keys:
|
|
220
|
+
|
|
221
|
+
```yaml
|
|
222
|
+
renderView:
|
|
223
|
+
- type: SelectField
|
|
224
|
+
dataLocation: ~.stage
|
|
225
|
+
label: "Stage:"
|
|
226
|
+
dynamicOptions: ~.stages
|
|
227
|
+
optionMapping:
|
|
228
|
+
label: ~.title
|
|
229
|
+
value: ~.id
|
|
230
|
+
|
|
231
|
+
data:
|
|
232
|
+
stages:
|
|
233
|
+
- id: "new"
|
|
234
|
+
title: "New"
|
|
235
|
+
- id: "won"
|
|
236
|
+
title: "Won"
|
|
237
|
+
stage: ""
|
|
238
|
+
```
|
|
239
|
+
|
|
214
240
|
### Custom Attributes
|
|
215
241
|
|
|
216
242
|
```yaml
|
|
@@ -369,7 +395,7 @@ data:
|
|
|
369
395
|
- **Automatic synchronization**: Unlike raw HTML elements that require manual setData actions
|
|
370
396
|
- **Flexible wrapper**: Avoids unnecessary HTML when not needed
|
|
371
397
|
- **Intelligent value handling**: Automatic conversion of boolean and null strings
|
|
372
|
-
- **Dynamic options**: Options can be provided via template evaluation using `dynamicOptions`
|
|
398
|
+
- **Dynamic options**: Options can be provided via template evaluation using `dynamicOptions`, from a list of any shape with `optionMapping`
|
|
373
399
|
- **Label flexibility**: Supports both simple strings and View component rendering
|
|
374
400
|
- **Empty state handling**: Gracefully handles empty options
|
|
375
401
|
|
|
@@ -43,13 +43,19 @@ renderView:
|
|
|
43
43
|
after: "(array, optional)"
|
|
44
44
|
details:
|
|
45
45
|
type: Markdown
|
|
46
|
-
content: "Static array of option objects with `label` and `value` properties."
|
|
46
|
+
content: "Static array of option objects with `label` and `value` properties (both support template evaluation)."
|
|
47
47
|
- term:
|
|
48
48
|
code: dynamicOptions
|
|
49
49
|
after: "(string, optional)"
|
|
50
50
|
details:
|
|
51
51
|
type: Markdown
|
|
52
|
-
content: "Template path to dynamic options array (e.g., `~.availableCategories`). Takes precedence over `options` if both are provided."
|
|
52
|
+
content: "Template path to dynamic options array (e.g., `~.availableCategories`). Takes precedence over `options` if both are provided. The items can be `{label, value}` objects, scalars (each scalar is used as both label and value), or objects of any shape mapped with `optionMapping`."
|
|
53
|
+
- term:
|
|
54
|
+
code: optionMapping
|
|
55
|
+
after: "(object, optional)"
|
|
56
|
+
details:
|
|
57
|
+
type: Markdown
|
|
58
|
+
content: "Builds each option from an item of the options list. It is evaluated once per item, **with the item as the template context**: `~.title` reads the item's `title`, `~` is the whole item, `~~.` still reads the global data. The mapped keys (`label`, `value`) override the item's keys."
|
|
53
59
|
- term:
|
|
54
60
|
code: allowEmptyStringAsValue
|
|
55
61
|
after: "(boolean, optional)"
|
|
@@ -222,6 +228,34 @@ renderView:
|
|
|
222
228
|
value: "science"
|
|
223
229
|
selectedCategory: ""
|
|
224
230
|
|
|
231
|
+
- type: RjBuildDescriber
|
|
232
|
+
title: "Dynamic Options with a Mapping"
|
|
233
|
+
description: "optionMapping reads the keys of items that have no label / value keys"
|
|
234
|
+
toDescribe:
|
|
235
|
+
renderView:
|
|
236
|
+
- type: SelectField
|
|
237
|
+
dataLocation: ~.stage
|
|
238
|
+
label: "Stage:"
|
|
239
|
+
dynamicOptions: ~.stages
|
|
240
|
+
optionMapping:
|
|
241
|
+
label: ~.title
|
|
242
|
+
value: ~.id
|
|
243
|
+
- type: div
|
|
244
|
+
attributes:
|
|
245
|
+
class: "mt-5 p-2.5 rounded border border-gray-300 dark:border-gray-600"
|
|
246
|
+
content:
|
|
247
|
+
- type: strong
|
|
248
|
+
content: "Selected stage: "
|
|
249
|
+
- ~.stage
|
|
250
|
+
data:
|
|
251
|
+
stages:
|
|
252
|
+
- id: "new"
|
|
253
|
+
title: "New"
|
|
254
|
+
- id: "qualified"
|
|
255
|
+
title: "Qualified"
|
|
256
|
+
- id: "won"
|
|
257
|
+
title: "Won"
|
|
258
|
+
stage: "new"
|
|
225
259
|
|
|
226
260
|
- type: Markdown
|
|
227
261
|
content: |
|
|
@@ -234,7 +268,7 @@ renderView:
|
|
|
234
268
|
- **Automatic synchronization**: Unlike raw HTML elements that require manual setData actions
|
|
235
269
|
- **Flexible wrapper**: Avoids unnecessary HTML when not needed
|
|
236
270
|
- **Intelligent value handling**: Automatic conversion of boolean and null strings
|
|
237
|
-
- **Dynamic options**: Options can be provided via template evaluation using `dynamicOptions`
|
|
271
|
+
- **Dynamic options**: Options can be provided via template evaluation using `dynamicOptions`, from a list of any shape with `optionMapping`
|
|
238
272
|
- **Label flexibility**: Supports both simple strings and View component rendering
|
|
239
273
|
- **Empty state handling**: Gracefully handles empty options
|
|
240
274
|
|
|
@@ -95,6 +95,38 @@ const onChange = (e) => {
|
|
|
95
95
|
|
|
96
96
|
This ensures consistent behavior across TextField, NumberField, SelectField, CheckBoxField, TextAreaField, and DateField components.
|
|
97
97
|
|
|
98
|
+
## evaluateFieldOptions Function
|
|
99
|
+
|
|
100
|
+
This utility returns the evaluated options of an option-based component (`SelectField`, `CheckBoxField`, `LabelFromValue`). Use it in a custom component that reads `options` / `dynamicOptions` / `optionMapping`, so that it supports the same option sources as the core components.
|
|
101
|
+
|
|
102
|
+
### Parameters
|
|
103
|
+
|
|
104
|
+
- `props` (object): The component props. The function reads `dynamicOptions`, `options` and `optionMapping`.
|
|
105
|
+
- `globalDataContext` (object): The global data context object
|
|
106
|
+
- `templateContext` (object): The template context object
|
|
107
|
+
|
|
108
|
+
### Return Value
|
|
109
|
+
|
|
110
|
+
An array of option objects with evaluated `label` and `value` (empty when the source is not an array):
|
|
111
|
+
|
|
112
|
+
- The source is `props.dynamicOptions` (a template reference, takes precedence) or the static `props.options` array.
|
|
113
|
+
- With `props.optionMapping`, the mapping is evaluated for each item, the item being the template context (`~`). The mapped keys override the item keys.
|
|
114
|
+
- Without `props.optionMapping`, the `label` and `value` of each item are evaluated in the component's template context. A scalar item is used as both label and value.
|
|
115
|
+
|
|
116
|
+
### Usage Example
|
|
117
|
+
|
|
118
|
+
```javascript
|
|
119
|
+
const options = evaluateFieldOptions({ props, globalDataContext, templateContext });
|
|
120
|
+
|
|
121
|
+
return (
|
|
122
|
+
<ul>
|
|
123
|
+
{options.map((option, index) => (
|
|
124
|
+
<li key={index} data-value={option.value}>{option.label}</li>
|
|
125
|
+
))}
|
|
126
|
+
</ul>
|
|
127
|
+
);
|
|
128
|
+
```
|
|
129
|
+
|
|
98
130
|
## Limitations
|
|
99
131
|
|
|
100
132
|
- Template data modification may not be the ideal approach (noted in code comments)
|