@ea-lab/reactive-json-docs 2.7.0 → 2.10.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/advanced-concepts/forward-update.yaml +1 -1
- package/public/rjbuild/docs/advanced-concepts/plugins/component-development.yaml +1 -1
- package/public/rjbuild/docs/advanced-concepts/plugins/index.yaml +1 -1
- package/public/rjbuild/docs/core/action/CustomEventListener.yaml +1 -1
- package/public/rjbuild/docs/core/element/form/AutocompleteField.yaml +1 -1
- package/public/rjbuild/docs/core/element/form/CheckBoxField.md +142 -18
- package/public/rjbuild/docs/core/element/form/CheckBoxField.yaml +133 -8
- package/public/rjbuild/docs/core/element/form/DateField.md +79 -0
- package/public/rjbuild/docs/core/element/form/DateField.yaml +115 -0
- package/public/rjbuild/docs/core/element/form/DateTimeField.md +60 -0
- package/public/rjbuild/docs/core/element/form/DateTimeField.yaml +97 -0
- package/public/rjbuild/docs/core/element/form/Input.yaml +1 -1
- package/public/rjbuild/docs/core/element/form/SelectField.md +36 -10
- package/public/rjbuild/docs/core/element/form/SelectField.yaml +38 -4
- package/public/rjbuild/docs/core/element/form/TextAreaField.yaml +1 -1
- 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/Join.yaml +1 -1
- 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/PageControls.yaml +1 -1
- package/public/rjbuild/docs/core/example/native-html-forms.md +19 -2
- package/public/rjbuild/docs/core/hook/index.yaml +1 -1
- package/public/rjbuild/docs/core/hook/usePagination.yaml +1 -1
- package/public/rjbuild/docs/core/hook/useTransformedAttributes.yaml +1 -1
- 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/docs-components/Mermaid.yaml +1 -1
- package/public/rjbuild/docs/docs-components/SyntaxHighlighter.yaml +1 -1
- package/public/rjbuild/docs/docs-components/index.yaml +1 -1
- 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 +19 -1
- package/public/rjbuild/docs/getting-started/rjbuild-structure.yaml +21 -1
- package/public/rjbuild/docs/getting-started/template-contexts-data-binding.yaml +1 -1
- package/public/rjbuild/docs/index.yaml +1 -1
- package/public/rjbuild/docs/install.yaml +1 -1
- package/public/rjbuild/docs/integration/bootstrap/element/form/CheckBoxField.yaml +1 -1
- package/public/rjbuild/docs/integration/bootstrap/element/form/DateField.yaml +1 -1
- package/public/rjbuild/docs/integration/bootstrap/element/form/NumberField.yaml +1 -1
- package/public/rjbuild/docs/integration/bootstrap/element/form/SelectField.yaml +1 -1
- package/public/rjbuild/docs/integration/bootstrap/element/form/TextAreaField.yaml +1 -1
- package/public/rjbuild/docs/integration/bootstrap/element/form/TextField.yaml +1 -1
- package/public/rjbuild/docs/integration/bootstrap/element/form/index.yaml +1 -1
- package/public/rjbuild/docs/integration/bootstrap/example/accordion.yaml +1 -1
- package/public/rjbuild/docs/integration/bootstrap/example/dynamic-content.yaml +1 -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.10.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.10.0",
|
|
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
|
|
@@ -218,5 +343,5 @@ renderView:
|
|
|
218
343
|
- For radio buttons, `multiple` is automatically set to `false` regardless of the `multiple` property
|
|
219
344
|
|
|
220
345
|
templates: {}
|
|
221
|
-
data:
|
|
346
|
+
data:
|
|
222
347
|
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# DateField
|
|
2
|
+
|
|
3
|
+
The `DateField` component is a thin convenience wrapper around [`Input`](Input.md) that renders an HTML `date` input (`<input type="date">`). It inherits every `Input` option (label, wrapper, attributes, actions, data binding) and adds an optional `storageFormat` for binding to a fixed-format storage string.
|
|
4
|
+
|
|
5
|
+
## Basic Syntax
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
- type: DateField
|
|
9
|
+
dataLocation: ~.startDate
|
|
10
|
+
label: "Start date:"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
By default the raw value of the HTML `date` input (`YYYY-MM-DD`) is stored as-is — identical to any other `Input` wrapper.
|
|
14
|
+
|
|
15
|
+
## Properties
|
|
16
|
+
|
|
17
|
+
- `dataLocation` (string, optional): Path to bind the field value in the data context. Without it, the value is stored in the template context under the component's `datafield`.
|
|
18
|
+
- `defaultFieldValue` (string, optional): Default value when no data is present.
|
|
19
|
+
- `label` (string or View props, optional): Field label text (supports template evaluation and View rendering). A wrapper `<div>` is added automatically when a label is present.
|
|
20
|
+
- `storageFormat` (string, optional): Binds the field to a fixed-format **storage string** instead of the raw input value. Accepts `"date"` or `"datetime"` (see [Storage format](#storage-format)). When omitted, the raw `YYYY-MM-DD` value is stored unchanged (original behavior).
|
|
21
|
+
- `attributes` (object, optional): Attributes applied to the wrapper `<div>` (or to the input itself when there is no wrapper).
|
|
22
|
+
- `inputAttributes` (object, optional): Attributes applied directly to the `<input>` element (e.g. `class`, `id`, `min`, `max`).
|
|
23
|
+
- `labelAttributes` (object, optional): Attributes applied to the label (`htmlFor` is managed automatically).
|
|
24
|
+
- `forceWrapper` (boolean, optional): Forces the presence (`true`) or absence (`false`) of the wrapper `<div>`. If omitted, the wrapper appears only when a label is present.
|
|
25
|
+
- `actions` (array, optional): Actions and conditional reactions to execute based on field state.
|
|
26
|
+
|
|
27
|
+
## Storage format
|
|
28
|
+
|
|
29
|
+
An HTML `date` input can only read and write `YYYY-MM-DD`. Backends often store dates in a fixed, stricter format — for example Drupal datetime fields validate against `Y-m-d` (date-only field) or `Y-m-d\TH:i:s` (datetime field). Feeding such a value straight to a `date` input leaves it blank (the input rejects a value carrying a time), and writing back `YYYY-MM-DD` is rejected by a datetime field.
|
|
30
|
+
|
|
31
|
+
Set `storageFormat` to bridge the two. It applies **two conversions**:
|
|
32
|
+
|
|
33
|
+
- **On read** — only the date part of the stored value is shown, so a datetime value like `2016-11-29T23:00:00` displays as `2016-11-29` instead of leaving the input empty.
|
|
34
|
+
- **On write** — the value is re-serialized to the target storage format:
|
|
35
|
+
- `storageFormat: date` → `YYYY-MM-DD`
|
|
36
|
+
- `storageFormat: datetime` → `YYYY-MM-DDT00:00:00` (the time is anchored at midnight, since a `date` input carries no time)
|
|
37
|
+
|
|
38
|
+
An empty input stores an empty string (clears the field). When `storageFormat` is omitted, no conversion happens and the raw input value is stored — so existing usages are unaffected.
|
|
39
|
+
|
|
40
|
+
> For editing a value that also carries a **time** the user should see and change, use [`DateTimeField`](DateTimeField.md) instead.
|
|
41
|
+
|
|
42
|
+
## Examples
|
|
43
|
+
|
|
44
|
+
### Default behavior (raw `YYYY-MM-DD`)
|
|
45
|
+
|
|
46
|
+
```yaml
|
|
47
|
+
renderView:
|
|
48
|
+
- type: DateField
|
|
49
|
+
dataLocation: ~.startDate
|
|
50
|
+
label: "Start date:"
|
|
51
|
+
- type: div
|
|
52
|
+
content:
|
|
53
|
+
- type: strong
|
|
54
|
+
content: "Stored value: "
|
|
55
|
+
- ~.startDate
|
|
56
|
+
|
|
57
|
+
data:
|
|
58
|
+
startDate: "2027-03-15"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### `storageFormat: datetime`
|
|
62
|
+
|
|
63
|
+
The `date` input drives a datetime storage string (time anchored at midnight):
|
|
64
|
+
|
|
65
|
+
```yaml
|
|
66
|
+
renderView:
|
|
67
|
+
- type: DateField
|
|
68
|
+
dataLocation: ~.closeDate
|
|
69
|
+
label: "Close date:"
|
|
70
|
+
storageFormat: datetime
|
|
71
|
+
- type: div
|
|
72
|
+
content:
|
|
73
|
+
- type: strong
|
|
74
|
+
content: "Stored value: "
|
|
75
|
+
- ~.closeDate
|
|
76
|
+
|
|
77
|
+
data:
|
|
78
|
+
closeDate: "2016-11-29T23:00:00"
|
|
79
|
+
```
|