@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.
Files changed (65) hide show
  1. package/package.json +2 -2
  2. package/public/rjbuild/docs/advanced-concepts/forward-update.yaml +1 -1
  3. package/public/rjbuild/docs/advanced-concepts/plugins/component-development.yaml +1 -1
  4. package/public/rjbuild/docs/advanced-concepts/plugins/index.yaml +1 -1
  5. package/public/rjbuild/docs/core/action/CustomEventListener.yaml +1 -1
  6. package/public/rjbuild/docs/core/element/form/AutocompleteField.yaml +1 -1
  7. package/public/rjbuild/docs/core/element/form/CheckBoxField.md +142 -18
  8. package/public/rjbuild/docs/core/element/form/CheckBoxField.yaml +133 -8
  9. package/public/rjbuild/docs/core/element/form/DateField.md +79 -0
  10. package/public/rjbuild/docs/core/element/form/DateField.yaml +115 -0
  11. package/public/rjbuild/docs/core/element/form/DateTimeField.md +60 -0
  12. package/public/rjbuild/docs/core/element/form/DateTimeField.yaml +97 -0
  13. package/public/rjbuild/docs/core/element/form/Input.yaml +1 -1
  14. package/public/rjbuild/docs/core/element/form/SelectField.md +36 -10
  15. package/public/rjbuild/docs/core/element/form/SelectField.yaml +38 -4
  16. package/public/rjbuild/docs/core/element/form/TextAreaField.yaml +1 -1
  17. package/public/rjbuild/docs/core/element/form/formElementsCommon.md +32 -0
  18. package/public/rjbuild/docs/core/element/html/Html.yaml +47 -0
  19. package/public/rjbuild/docs/core/element/html/Join.yaml +1 -1
  20. package/public/rjbuild/docs/core/element/html/LabelFromValue.md +159 -0
  21. package/public/rjbuild/docs/core/element/html/LabelFromValue.yaml +163 -10
  22. package/public/rjbuild/docs/core/element/special/PageControls.yaml +1 -1
  23. package/public/rjbuild/docs/core/example/native-html-forms.md +19 -2
  24. package/public/rjbuild/docs/core/hook/index.yaml +1 -1
  25. package/public/rjbuild/docs/core/hook/usePagination.yaml +1 -1
  26. package/public/rjbuild/docs/core/hook/useTransformedAttributes.yaml +1 -1
  27. package/public/rjbuild/docs/core/reaction/collectField.md +51 -0
  28. package/public/rjbuild/docs/core/reaction/collectField.yaml +81 -0
  29. package/public/rjbuild/docs/core/reaction/fetchData.md +21 -1
  30. package/public/rjbuild/docs/core/reaction/fetchData.yaml +2 -2
  31. package/public/rjbuild/docs/core/reaction/index.md +5 -0
  32. package/public/rjbuild/docs/core/reaction/index.yaml +5 -0
  33. package/public/rjbuild/docs/core/reaction/joinData.md +51 -0
  34. package/public/rjbuild/docs/core/reaction/joinData.yaml +87 -0
  35. package/public/rjbuild/docs/core/reaction/printPage.md +22 -0
  36. package/public/rjbuild/docs/core/reaction/printPage.yaml +29 -0
  37. package/public/rjbuild/docs/core/reaction/redirectNow.md +20 -2
  38. package/public/rjbuild/docs/core/reaction/redirectNow.yaml +24 -3
  39. package/public/rjbuild/docs/core/reaction/setClipboardData.md +35 -6
  40. package/public/rjbuild/docs/core/reaction/setClipboardData.yaml +18 -6
  41. package/public/rjbuild/docs/core/reaction/stringifyData.md +45 -0
  42. package/public/rjbuild/docs/core/reaction/stringifyData.yaml +58 -0
  43. package/public/rjbuild/docs/core/reaction/submitData.md +1 -1
  44. package/public/rjbuild/docs/core/reaction/submitData.yaml +4 -2
  45. package/public/rjbuild/docs/core/reaction/toggleData.md +72 -0
  46. package/public/rjbuild/docs/core/reaction/toggleData.yaml +77 -0
  47. package/public/rjbuild/docs/docs-components/Mermaid.yaml +1 -1
  48. package/public/rjbuild/docs/docs-components/SyntaxHighlighter.yaml +1 -1
  49. package/public/rjbuild/docs/docs-components/index.yaml +1 -1
  50. package/public/rjbuild/docs/getting-started/reactions.md +5 -0
  51. package/public/rjbuild/docs/getting-started/reactions.yaml +5 -0
  52. package/public/rjbuild/docs/getting-started/rjbuild-structure.md +19 -1
  53. package/public/rjbuild/docs/getting-started/rjbuild-structure.yaml +21 -1
  54. package/public/rjbuild/docs/getting-started/template-contexts-data-binding.yaml +1 -1
  55. package/public/rjbuild/docs/index.yaml +1 -1
  56. package/public/rjbuild/docs/install.yaml +1 -1
  57. package/public/rjbuild/docs/integration/bootstrap/element/form/CheckBoxField.yaml +1 -1
  58. package/public/rjbuild/docs/integration/bootstrap/element/form/DateField.yaml +1 -1
  59. package/public/rjbuild/docs/integration/bootstrap/element/form/NumberField.yaml +1 -1
  60. package/public/rjbuild/docs/integration/bootstrap/element/form/SelectField.yaml +1 -1
  61. package/public/rjbuild/docs/integration/bootstrap/element/form/TextAreaField.yaml +1 -1
  62. package/public/rjbuild/docs/integration/bootstrap/element/form/TextField.yaml +1 -1
  63. package/public/rjbuild/docs/integration/bootstrap/element/form/index.yaml +1 -1
  64. package/public/rjbuild/docs/integration/bootstrap/example/accordion.yaml +1 -1
  65. package/public/rjbuild/docs/integration/bootstrap/example/dynamic-content.yaml +1 -1
@@ -0,0 +1,115 @@
1
+ renderView:
2
+ - type: Markdown
3
+ content: |
4
+ # DateField
5
+
6
+ The `DateField` component is a thin convenience wrapper around [`Input`](/docs/core/element/form/Input) 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.
7
+
8
+ - type: Markdown
9
+ content: |
10
+ ## Basic Syntax
11
+
12
+ ```yaml
13
+ - type: DateField
14
+ dataLocation: ~.startDate
15
+ label: "Start date:"
16
+ ```
17
+
18
+ By default the raw value of the HTML `date` input (`YYYY-MM-DD`) is stored as-is — identical to any other `Input` wrapper.
19
+
20
+ ## Properties
21
+
22
+ - type: DefinitionList
23
+ content:
24
+ - term:
25
+ code: dataLocation
26
+ after: "(string, optional)"
27
+ details: "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`."
28
+ - term:
29
+ code: defaultFieldValue
30
+ after: "(string, optional)"
31
+ details: "Default value when no data is present."
32
+ - term:
33
+ code: label
34
+ after: "(string or View props, optional)"
35
+ details: "Field label text (supports template evaluation and View rendering). A wrapper `<div>` is added automatically when a label is present."
36
+ - term:
37
+ code: storageFormat
38
+ after: "(string, optional)"
39
+ details:
40
+ type: Markdown
41
+ content: |
42
+ Binds the field to a fixed-format **storage string** instead of the raw input value. Accepts `"date"` or `"datetime"`. See [Storage format](#storage-format) below. When omitted, the raw `YYYY-MM-DD` value is stored unchanged (original behavior).
43
+ - term:
44
+ code: attributes
45
+ after: "(object, optional)"
46
+ details: "Attributes applied to the wrapper `<div>` (or to the input itself when there is no wrapper)."
47
+ - term:
48
+ code: inputAttributes
49
+ after: "(object, optional)"
50
+ details: "Attributes applied directly to the `<input>` element (e.g. `class`, `id`, `min`, `max`)."
51
+ - term:
52
+ code: labelAttributes
53
+ after: "(object, optional)"
54
+ details: "Attributes applied to the label (`htmlFor` is managed automatically)."
55
+ - term:
56
+ code: forceWrapper
57
+ after: "(boolean, optional)"
58
+ details: "Forces the presence (`true`) or absence (`false`) of the wrapper `<div>`. If omitted, the wrapper appears only when a label is present."
59
+ - term:
60
+ code: actions
61
+ after: "(array, optional)"
62
+ details: "Actions and conditional reactions to execute based on field state (hide, tooltip, setData, …)."
63
+
64
+ - type: Markdown
65
+ content: |
66
+ ## Storage format
67
+
68
+ 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.
69
+
70
+ Set `storageFormat` to bridge the two. It applies **two conversions**:
71
+
72
+ - **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.
73
+ - **On write** — the value is re-serialized to the target storage format:
74
+ - `storageFormat: date` → `YYYY-MM-DD`
75
+ - `storageFormat: datetime` → `YYYY-MM-DDT00:00:00` (the time is anchored at midnight, since a `date` input carries no time)
76
+
77
+ 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.
78
+
79
+ > For editing a value that also carries a **time** the user should see and change, use [`DateTimeField`](/docs/core/element/form/DateTimeField) instead.
80
+
81
+ - type: RjBuildDescriber
82
+ title: "Default behavior (raw YYYY-MM-DD)"
83
+ description: "Without storageFormat, the raw input value is stored as-is."
84
+ toDescribe:
85
+ renderView:
86
+ - type: DateField
87
+ dataLocation: ~.startDate
88
+ label: "Start date:"
89
+ - type: div
90
+ content:
91
+ - type: strong
92
+ content: "Stored value: "
93
+ - ~.startDate
94
+ data:
95
+ startDate: "2027-03-15"
96
+
97
+ - type: RjBuildDescriber
98
+ title: "storageFormat: datetime"
99
+ description: "The date input drives a datetime storage string (time anchored at midnight)."
100
+ toDescribe:
101
+ renderView:
102
+ - type: DateField
103
+ dataLocation: ~.closeDate
104
+ label: "Close date:"
105
+ storageFormat: datetime
106
+ - type: div
107
+ content:
108
+ - type: strong
109
+ content: "Stored value: "
110
+ - ~.closeDate
111
+ data:
112
+ closeDate: "2016-11-29T23:00:00"
113
+
114
+ templates: {}
115
+ data:
@@ -0,0 +1,60 @@
1
+ # DateTimeField
2
+
3
+ The `DateTimeField` component is a thin convenience wrapper around [`Input`](Input.md) that renders an HTML `datetime-local` input (`<input type="datetime-local">`). It inherits every `Input` option and adds an optional `storageFormat` for binding to a fixed-format storage string.
4
+
5
+ ## Basic Syntax
6
+
7
+ ```yaml
8
+ - type: DateTimeField
9
+ dataLocation: ~.meetingAt
10
+ label: "Meeting date and time:"
11
+ ```
12
+
13
+ By default the raw value of the HTML `datetime-local` input (`YYYY-MM-DDTHH:MM`) is stored as-is.
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-DDTHH:MM` 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`, `step`).
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 `datetime-local` input reads and writes `YYYY-MM-DDTHH:MM` — **without seconds** (browsers omit the `:00` seconds unless a sub-minute `step` is set, and even then behavior varies). A backend datetime field that validates against a fixed format such as Drupal's `Y-m-d\TH:i:s` therefore rejects the raw value.
30
+
31
+ Set `storageFormat` to bridge the two. It applies **two conversions**:
32
+
33
+ - **On read** — the date + time part of the stored value is shown (a stored `2016-11-29T23:00:00` displays as `2016-11-29T23:00`).
34
+ - **On write** — the value is re-serialized to the target storage format:
35
+ - `storageFormat: datetime` → `YYYY-MM-DDTHH:MM:SS` (seconds appended; `00` when the input has no time)
36
+ - `storageFormat: date` → `YYYY-MM-DD` (time dropped)
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
+ ## Example
41
+
42
+ ### `storageFormat: datetime`
43
+
44
+ The `datetime-local` input drives a datetime storage string, with seconds:
45
+
46
+ ```yaml
47
+ renderView:
48
+ - type: DateTimeField
49
+ dataLocation: ~.closeDate
50
+ label: "Close date and time:"
51
+ storageFormat: datetime
52
+ - type: div
53
+ content:
54
+ - type: strong
55
+ content: "Stored value: "
56
+ - ~.closeDate
57
+
58
+ data:
59
+ closeDate: "2016-11-29T23:00:00"
60
+ ```
@@ -0,0 +1,97 @@
1
+ renderView:
2
+ - type: Markdown
3
+ content: |
4
+ # DateTimeField
5
+
6
+ The `DateTimeField` component is a thin convenience wrapper around [`Input`](/docs/core/element/form/Input) that renders an HTML `datetime-local` input (`<input type="datetime-local">`). It inherits every `Input` option and adds an optional `storageFormat` for binding to a fixed-format storage string.
7
+
8
+ - type: Markdown
9
+ content: |
10
+ ## Basic Syntax
11
+
12
+ ```yaml
13
+ - type: DateTimeField
14
+ dataLocation: ~.meetingAt
15
+ label: "Meeting date and time:"
16
+ ```
17
+
18
+ By default the raw value of the HTML `datetime-local` input (`YYYY-MM-DDTHH:MM`) is stored as-is.
19
+
20
+ ## Properties
21
+
22
+ - type: DefinitionList
23
+ content:
24
+ - term:
25
+ code: dataLocation
26
+ after: "(string, optional)"
27
+ details: "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`."
28
+ - term:
29
+ code: defaultFieldValue
30
+ after: "(string, optional)"
31
+ details: "Default value when no data is present."
32
+ - term:
33
+ code: label
34
+ after: "(string or View props, optional)"
35
+ details: "Field label text (supports template evaluation and View rendering). A wrapper `<div>` is added automatically when a label is present."
36
+ - term:
37
+ code: storageFormat
38
+ after: "(string, optional)"
39
+ details:
40
+ type: Markdown
41
+ content: |
42
+ Binds the field to a fixed-format **storage string** instead of the raw input value. Accepts `"date"` or `"datetime"`. See [Storage format](#storage-format) below. When omitted, the raw `YYYY-MM-DDTHH:MM` value is stored unchanged (original behavior).
43
+ - term:
44
+ code: attributes
45
+ after: "(object, optional)"
46
+ details: "Attributes applied to the wrapper `<div>` (or to the input itself when there is no wrapper)."
47
+ - term:
48
+ code: inputAttributes
49
+ after: "(object, optional)"
50
+ details: "Attributes applied directly to the `<input>` element (e.g. `class`, `id`, `min`, `max`, `step`)."
51
+ - term:
52
+ code: labelAttributes
53
+ after: "(object, optional)"
54
+ details: "Attributes applied to the label (`htmlFor` is managed automatically)."
55
+ - term:
56
+ code: forceWrapper
57
+ after: "(boolean, optional)"
58
+ details: "Forces the presence (`true`) or absence (`false`) of the wrapper `<div>`. If omitted, the wrapper appears only when a label is present."
59
+ - term:
60
+ code: actions
61
+ after: "(array, optional)"
62
+ details: "Actions and conditional reactions to execute based on field state."
63
+
64
+ - type: Markdown
65
+ content: |
66
+ ## Storage format
67
+
68
+ An HTML `datetime-local` input reads and writes `YYYY-MM-DDTHH:MM` — **without seconds** (browsers omit the `:00` seconds unless a sub-minute `step` is set, and even then behavior varies). A backend datetime field that validates against a fixed format such as Drupal's `Y-m-d\TH:i:s` therefore rejects the raw value.
69
+
70
+ Set `storageFormat` to bridge the two. It applies **two conversions**:
71
+
72
+ - **On read** — the date + time part of the stored value is shown (a stored `2016-11-29T23:00:00` displays as `2016-11-29T23:00`).
73
+ - **On write** — the value is re-serialized to the target storage format:
74
+ - `storageFormat: datetime` → `YYYY-MM-DDTHH:MM:SS` (seconds appended; `00` when the input has no time)
75
+ - `storageFormat: date` → `YYYY-MM-DD` (time dropped)
76
+
77
+ 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.
78
+
79
+ - type: RjBuildDescriber
80
+ title: "storageFormat: datetime"
81
+ description: "The datetime-local input drives a datetime storage string, with seconds."
82
+ toDescribe:
83
+ renderView:
84
+ - type: DateTimeField
85
+ dataLocation: ~.closeDate
86
+ label: "Close date and time:"
87
+ storageFormat: datetime
88
+ - type: div
89
+ content:
90
+ - type: strong
91
+ content: "Stored value: "
92
+ - ~.closeDate
93
+ data:
94
+ closeDate: "2016-11-29T23:00:00"
95
+
96
+ templates: {}
97
+ data:
@@ -569,4 +569,4 @@ renderView:
569
569
  - Integrated label is limited: for conditional actions, prefer separated label
570
570
 
571
571
  templates: {}
572
- data: {}
572
+ data:
@@ -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
- Option labels support template evaluation, allowing dynamic content:
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: ~.item
119
+ dataLocation: ~.owner
119
120
  options:
120
- - label: "Item: ~.itemName"
121
- value: "item1"
122
- - label: ["Count: ", ~.count]
123
- value: "item2"
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
 
@@ -248,5 +282,5 @@ renderView:
248
282
  - Empty string handling requires explicit `allowEmptyStringAsValue` for semantic distinction
249
283
 
250
284
  templates: {}
251
- data: {}
285
+ data:
252
286
 
@@ -135,5 +135,5 @@ renderView:
135
135
  - Template evaluation for `rows` should return a number
136
136
 
137
137
  templates: {}
138
- data: {}
138
+ data:
139
139
 
@@ -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)
@@ -74,6 +74,53 @@ renderView:
74
74
  class: ""
75
75
  txt: Hello world!
76
76
 
77
+ - type: Markdown
78
+ content: |
79
+ ## URL attributes
80
+
81
+ The URL attributes (`href`, `src`, `action`, `formAction`, `poster`) accept an array of segments, in the format of the `src` of `additionalDataSource` (see *Dynamic URLs with `src` as Array* in [RjBuild structure](../../getting-started/rjbuild-structure)). The references are evaluated in the current template context, so each item of a `Switch` gets its own URL:
82
+
83
+ ```yaml
84
+ - type: a
85
+ attributes:
86
+ href:
87
+ - "/article/"
88
+ - ~.year
89
+ - "/"
90
+ - segment: ~.slug
91
+ required: true
92
+ content: ~.title
93
+ ```
94
+
95
+ When a required segment is empty, the attribute is omitted. An array in another attribute is evaluated as before (each item separately).
96
+
97
+ - type: Markdown
98
+ content: |
99
+ ## Form controls
100
+
101
+ `input`, `textarea` and `select` elements are rendered as **controlled** React elements: their `value` defaults to `""`.
102
+
103
+ A checkbox or radio `input` is controlled by its `checked` attribute, which defaults to `false`. Without a binding, the input never shows as checked, whatever its reactions do to the data. Bind it to the data:
104
+
105
+ - a boolean: `checked: ~.isSelected` (a falsy value leaves the input unchecked);
106
+ - a comparison or a list membership: an `attributeTransforms` entry setting `checked`, with a condition (`is`, `contains`...).
107
+
108
+ ```yaml
109
+ - type: input
110
+ attributes:
111
+ type: checkbox
112
+ value: ~.label
113
+ attributeTransforms:
114
+ - what: setAttributeValue
115
+ name: checked
116
+ mode: replace
117
+ value: true
118
+ when: ~~.lead.sessions
119
+ contains: ~.label
120
+ ```
121
+
122
+ A warning is logged when a checkbox or radio has event reactions (`on: change`...) but neither a `checked` attribute nor an attribute transform on `checked`. To store a value or a list of values, prefer [CheckBoxField](../form/CheckBoxField), which binds `checked` itself.
123
+
77
124
  - type: Markdown
78
125
  content: |
79
126
  ## Limitations
@@ -110,4 +110,4 @@ renderView:
110
110
  - No per-item formatting; all elements are joined as plain strings.
111
111
 
112
112
  templates: {}
113
- data: {}
113
+ data: