@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,159 @@
1
+ # LabelFromValue
2
+
3
+ The `LabelFromValue` component displays the **label** associated with a value, using an option-like structure as data source. It is the read-only counterpart of the form fields: the same `{label, value}` list feeding a [`SelectField`](../form/SelectField.md) or a [`CheckBoxField`](../form/CheckBoxField.md) can be reused to render the selected value as text.
4
+
5
+ ## Basic Syntax
6
+
7
+ ```yaml
8
+ - type: LabelFromValue
9
+ dataLocation: ~.status
10
+ options:
11
+ - label: "Active"
12
+ value: 1
13
+ - label: "Inactive"
14
+ value: 2
15
+ ```
16
+
17
+ With `status: 2` in the data, this renders `Inactive`.
18
+
19
+ ## Properties
20
+
21
+ - `dataLocation` (string, optional): Path to the value to resolve. Without it, the value is read from the template context under the component's `datafield`.
22
+ - `options` (array, optional): Array of `{label, value}` objects (both support template evaluation). Ignored when `dynamicOptions` is set.
23
+ - `dynamicOptions` (any, optional): Template reference resolving to the options array (e.g. `~~.allStages`, typically options loaded from a backend). Takes precedence over `options`. 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`.
24
+ - `optionMapping` (object, optional): Builds each option from an item of the options list, exactly like in `SelectField` and `CheckBoxField`. It is evaluated once per item, **with the item as the template context** (`~.title` reads the item's `title`, `~~.` still reads the global data). The mapped keys override the item's keys.
25
+ - `defaultFieldValue` (any, optional): Value used when no data is present.
26
+ - `loose` (boolean, optional): Matches the options by `String()`-coerced equality instead of the default strict one (see [Loose matching](#loose-matching)). Omitted or `false` = strict equality (original behavior).
27
+ - `actions` (array, optional): Actions and conditional reactions to execute based on component state (hide, tooltip, …).
28
+
29
+ The label is rendered through the `View` engine, so it can be a plain string or a full component structure (`{type: strong, content: …}`).
30
+
31
+ ## Loose matching
32
+
33
+ By default an option matches the current value only on **strict** equality (`===`), so `1` (number) and `"1"` (string) are two different values and no label is found.
34
+
35
+ This bites when the JS type of the same identifier is not guaranteed across sources. A typical case is a decoupled backend that renders an entity reference id as a **string** when reading the entity, but echoes it back as a **number** in its save response: the label is correct on load, then disappears right after a save — until a full reload restores the original type.
36
+
37
+ Set `loose: true` to compare the values as strings instead:
38
+
39
+ ```yaml
40
+ - type: LabelFromValue
41
+ dataLocation: ~.stage
42
+ dynamicOptions: ~~.allStages
43
+ loose: true
44
+ ```
45
+
46
+ Nullish values are never coerced: an empty value (`null` / `undefined`) still matches nothing, so it cannot accidentally match an option whose value is the `"null"` string. `loose` is opt-in — omitted, the component behaves exactly as before, so existing usages are unaffected.
47
+
48
+ ## Examples
49
+
50
+ ### Display the label of a selected value
51
+
52
+ ```yaml
53
+ renderView:
54
+ - type: SelectField
55
+ dataLocation: ~.status
56
+ label: "Status"
57
+ options:
58
+ - label: "Active"
59
+ value: 1
60
+ - label: "Inactive"
61
+ value: 2
62
+ - label: "Pending"
63
+ value: 3
64
+ - type: div
65
+ content:
66
+ - type: strong
67
+ content: "Label: "
68
+ - type: LabelFromValue
69
+ dataLocation: ~.status
70
+ options:
71
+ - label: "Active"
72
+ value: 1
73
+ - label: "Inactive"
74
+ value: 2
75
+ - label: "Pending"
76
+ value: 3
77
+
78
+ data:
79
+ status: 3
80
+ ```
81
+
82
+ Renders: `Label: Pending`.
83
+
84
+ ### Options loaded from a backend, with loose matching
85
+
86
+ ```yaml
87
+ renderView:
88
+ - type: LabelFromValue
89
+ dataLocation: ~~.deal.data.stage
90
+ dynamicOptions: ~~.allStages
91
+ loose: true
92
+
93
+ data:
94
+ # allStages is typically fetched (additionalDataSource) as
95
+ # [{label: "Discovery", value: "12"}, {label: "Negotiation", value: "13"}, …]
96
+ deal:
97
+ data:
98
+ stage: 13
99
+ ```
100
+
101
+ The value is a number while the option values are strings: without `loose`, nothing would be displayed.
102
+
103
+ ### Options of any shape, with a mapping
104
+
105
+ ```yaml
106
+ renderView:
107
+ - type: LabelFromValue
108
+ dataLocation: ~~.deal.stage
109
+ dynamicOptions: ~~.stages
110
+ optionMapping:
111
+ label: ~.title
112
+ value: ~.id
113
+
114
+ data:
115
+ stages:
116
+ - id: "new"
117
+ title: "New"
118
+ - id: "won"
119
+ title: "Won"
120
+ deal:
121
+ stage: "won"
122
+ ```
123
+
124
+ Renders: `Won`. Use the same `optionMapping` as the `SelectField` editing the value.
125
+
126
+ ### Inside a template, against global data
127
+
128
+ ```yaml
129
+ templates:
130
+ userCard:
131
+ type: div
132
+ content:
133
+ - "Admin: "
134
+ - type: LabelFromValue
135
+ dataLocation: ~~.isAdmin
136
+ options:
137
+ - label: "Yes"
138
+ value: true
139
+ - label: "No"
140
+ value: false
141
+
142
+ renderView:
143
+ - load: userCard
144
+
145
+ data:
146
+ isAdmin: true
147
+ ```
148
+
149
+ ## Notes
150
+
151
+ - The first matching option wins; the options list is not deduplicated.
152
+ - When no option matches the value (or the matched option carries no `label`), nothing is displayed — the value itself is not used as a fallback label.
153
+ - An empty value (`null`, `undefined`, `""`) therefore renders nothing, unless an option explicitly declares that value.
154
+
155
+ ## Limitations
156
+
157
+ - No support for grouped options or nested option structures.
158
+ - No built-in formatting of the label (wrap the component if needed).
159
+ - Multi-value data (an array of values) is not supported: the whole array is compared to each option value.
@@ -3,7 +3,23 @@ renderView:
3
3
  content: |
4
4
  # LabelFromValue
5
5
 
6
- The `LabelFromValue` component displays the label associated with a value, using an option-like structure. It is useful for showing the display label of a value selected in a SelectField or any value/label mapping.
6
+ The `LabelFromValue` component displays the **label** associated with a value, using an option-like structure as data source. It is the read-only counterpart of the form fields: the same `{label, value}` list feeding a [`SelectField`](/docs/core/element/form/SelectField) or a [`CheckBoxField`](/docs/core/element/form/CheckBoxField) can be reused to render the selected value as text.
7
+
8
+ - type: Markdown
9
+ content: |
10
+ ## Basic Syntax
11
+
12
+ ```yaml
13
+ - type: LabelFromValue
14
+ dataLocation: ~.status
15
+ options:
16
+ - label: "Active"
17
+ value: 1
18
+ - label: "Inactive"
19
+ value: 2
20
+ ```
21
+
22
+ With `status: 2` in the data, this renders `Inactive`.
7
23
 
8
24
  ## Properties
9
25
 
@@ -11,22 +27,44 @@ renderView:
11
27
  content:
12
28
  - term:
13
29
  code: dataLocation
14
- after: "(string, required)"
15
- details: "Path to the value."
30
+ after: "(string, optional)"
31
+ details: "Path to the value to resolve. Without it, the value is read from the template context under the component's `datafield`."
16
32
  - term:
17
33
  code: options
18
34
  after: "(array, optional)"
19
35
  details:
20
36
  type: Markdown
21
- content: "Array of `{label, value}` objects."
37
+ content: "Array of `{label, value}` objects (both support template evaluation). Ignored when `dynamicOptions` is set."
22
38
  - term:
23
39
  code: dynamicOptions
24
40
  after: "(any, optional)"
25
- details: "Template value for dynamic options."
41
+ details:
42
+ type: Markdown
43
+ content: "Template reference resolving to the options array (e.g. `~~.allStages`, typically options loaded from a backend). Takes precedence over `options`. 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`."
44
+ - term:
45
+ code: optionMapping
46
+ after: "(object, optional)"
47
+ details:
48
+ type: Markdown
49
+ content: "Builds each option from an item of the options list, exactly like in `SelectField` and `CheckBoxField`. It is evaluated once per item, **with the item as the template context** (`~.title` reads the item's `title`, `~~.` still reads the global data). The mapped keys override the item's keys."
26
50
  - term:
27
51
  code: defaultFieldValue
28
52
  after: "(any, optional)"
29
- details: "Default value if none is set."
53
+ details: "Value used when no data is present."
54
+ - term:
55
+ code: loose
56
+ after: "(boolean, optional)"
57
+ details:
58
+ type: Markdown
59
+ content: "Matches the options by `String()`-coerced equality instead of the default strict one. See [Loose matching](#loose-matching). Omitted or `false` = strict equality (original behavior)."
60
+ - term:
61
+ code: actions
62
+ after: "(array, optional)"
63
+ details: "Actions and conditional reactions to execute based on component state (hide, tooltip, …)."
64
+
65
+ - type: Markdown
66
+ content: |
67
+ The label is rendered through the `View` engine, so it can be a plain string or a full component structure (`{type: strong, content: …}`).
30
68
 
31
69
  - type: RjBuildDescriber
32
70
  title: "Interactive Example: Display label from value"
@@ -64,8 +102,123 @@ renderView:
64
102
 
65
103
  - type: Markdown
66
104
  content: |
105
+ ## Loose matching
106
+
107
+ By default an option matches the current value only on **strict** equality (`===`), so `1` (number) and `"1"` (string) are two different values and no label is found.
108
+
109
+ This bites when the JS type of the same identifier is not guaranteed across sources. A typical case is a decoupled backend that renders an entity reference id as a **string** when reading the entity, but echoes it back as a **number** in its save response: the label is correct on load, then disappears right after a save — until a full reload restores the original type.
110
+
111
+ Set `loose: true` to compare the values as strings instead:
112
+
113
+ ```yaml
114
+ - type: LabelFromValue
115
+ dataLocation: ~.stage
116
+ dynamicOptions: ~~.allStages
117
+ loose: true
118
+ ```
119
+
120
+ Nullish values are never coerced: an empty value (`null` / `undefined`) still matches nothing, so it cannot accidentally match an option whose value is the `"null"` string. `loose` is opt-in — omitted, the component behaves exactly as before.
121
+
122
+ - type: RjBuildDescriber
123
+ title: "Interactive Example: Loose matching"
124
+ description:
125
+ - type: Markdown
126
+ content: |
127
+ Both components read the same value, `"2"` (a **string**), against options whose values are **numbers**. Only the loose one finds the label.
128
+ toDescribe:
129
+ renderView:
130
+ - type: div
131
+ content:
132
+ - type: strong
133
+ content: "Strict (default): "
134
+ - type: LabelFromValue
135
+ dataLocation: ~.status
136
+ options:
137
+ - label: "Active"
138
+ value: 1
139
+ - label: "Inactive"
140
+ value: 2
141
+ - label: "Pending"
142
+ value: 3
143
+ - type: div
144
+ content:
145
+ - type: strong
146
+ content: "Loose: "
147
+ - type: LabelFromValue
148
+ dataLocation: ~.status
149
+ loose: true
150
+ options:
151
+ - label: "Active"
152
+ value: 1
153
+ - label: "Inactive"
154
+ value: 2
155
+ - label: "Pending"
156
+ value: 3
157
+ data:
158
+ status: "2"
159
+
160
+ - type: RjBuildDescriber
161
+ title: "Interactive Example: Options loaded from a backend"
162
+ description:
163
+ - type: Markdown
164
+ content: |
165
+ `dynamicOptions` reads the options from the data (here `allStages`, as an `additionalDataSource` would provide them). The value is a **number** while the option values are **strings**, hence `loose: true`.
166
+ toDescribe:
167
+ renderView:
168
+ - type: div
169
+ content:
170
+ - type: strong
171
+ content: "Stage: "
172
+ - type: LabelFromValue
173
+ dataLocation: ~~.deal.data.stage
174
+ dynamicOptions: ~~.allStages
175
+ loose: true
176
+ data:
177
+ allStages:
178
+ - label: "Discovery"
179
+ value: "12"
180
+ - label: "Negotiation"
181
+ value: "13"
182
+ - label: "Closed won"
183
+ value: "14"
184
+ deal:
185
+ data:
186
+ stage: 13
187
+
188
+ - type: RjBuildDescriber
189
+ title: "Interactive Example: Inside a template, against global data"
190
+ description:
191
+ - type: Markdown
192
+ content: |
193
+ Within a template, `~~.` reaches the global data while `~.` would stay in the template scope.
194
+ toDescribe:
195
+ renderView:
196
+ - load: userCard
197
+ templates:
198
+ userCard:
199
+ type: div
200
+ content:
201
+ - "Admin: "
202
+ - type: LabelFromValue
203
+ dataLocation: ~~.isAdmin
204
+ options:
205
+ - label: "Yes"
206
+ value: true
207
+ - label: "No"
208
+ value: false
209
+ data:
210
+ isAdmin: true
211
+
212
+ - type: Markdown
213
+ content: |
214
+ ## Notes
215
+
216
+ - The first matching option wins; the options list is not deduplicated.
217
+ - When no option matches the value (or the matched option carries no `label`), nothing is displayed — the value itself is not used as a fallback label.
218
+ - An empty value (`null`, `undefined`, `""`) therefore renders nothing, unless an option explicitly declares that value.
219
+
67
220
  ## Limitations
68
- - Only the first matching label is displayed; duplicate values in options are not supported.
69
- - No support for grouped options or nested structures.
70
- - No built-in formatting for the label (use a wrapper if needed).
71
- - If no options are provided, the raw value is shown.
221
+
222
+ - No support for grouped options or nested option structures.
223
+ - No built-in formatting of the label (wrap the component if needed).
224
+ - Multi-value data (an array of values) is not supported: the whole array is compared to each option value.
@@ -131,4 +131,4 @@ renderView:
131
131
 
132
132
  templates:
133
133
 
134
- data: {}
134
+ data:
@@ -146,13 +146,22 @@ Use the `for` attribute to associate labels with form elements for accessibility
146
146
  ```
147
147
 
148
148
  ### Radio Buttons
149
+
150
+ Each radio must be checked only when the stored value is its own. `checked: ~.selectedSize` would check every radio as soon as a size is selected, so compare the value with an attribute transform:
151
+
149
152
  ```yaml
150
153
  - type: input
151
154
  attributes:
152
155
  type: "radio"
153
156
  name: "size"
154
157
  value: "small"
155
- checked: ~.selectedSize
158
+ attributeTransforms:
159
+ - what: setAttributeValue
160
+ name: checked
161
+ mode: replace
162
+ value: true
163
+ when: ~.selectedSize
164
+ is: "small"
156
165
  actions:
157
166
  - what: setData
158
167
  on: change
@@ -164,7 +173,13 @@ Use the `for` attribute to associate labels with form elements for accessibility
164
173
  type: "radio"
165
174
  name: "size"
166
175
  value: "large"
167
- checked: ~.selectedSize
176
+ attributeTransforms:
177
+ - what: setAttributeValue
178
+ name: checked
179
+ mode: replace
180
+ value: true
181
+ when: ~.selectedSize
182
+ is: "large"
168
183
  actions:
169
184
  - what: setData
170
185
  on: change
@@ -172,6 +187,8 @@ Use the `for` attribute to associate labels with form elements for accessibility
172
187
  value: "large"
173
188
  ```
174
189
 
190
+ A checkbox or radio without a `checked` binding (attribute or attribute transform) is forced to unchecked and never shows a user's click. [CheckBoxField](../element/form/CheckBoxField.md) with `controlType: radio` handles all of this by itself.
191
+
175
192
  ## Advanced Patterns
176
193
 
177
194
  ### Form Validation with Conditional Actions
@@ -41,4 +41,4 @@ renderView:
41
41
  The core Reactive-JSON library uses this same mechanism internally to provide its built-in hooks, ensuring consistency between core functionality and custom extensions.
42
42
 
43
43
  templates: {}
44
- data: {}
44
+ data:
@@ -316,4 +316,4 @@ renderView:
316
316
  - Future version: support for synchronization with external data changes
317
317
 
318
318
  templates: {}
319
- data: {}
319
+ data:
@@ -161,4 +161,4 @@ renderView:
161
161
  For details on individual transformers, see [attributeTransformer documentation](../attributeTransformer/index).
162
162
 
163
163
  templates: {}
164
- data: {}
164
+ data:
@@ -0,0 +1,51 @@
1
+ # Reaction: collectField
2
+
3
+ The `collectField` reaction writes the values of one field of every item of a collection, as an array. Typical use: a "select all" checkbox that writes the identifiers of the listed items.
4
+
5
+ ## Properties
6
+
7
+ - `from` (string, required): The collection (template syntax), an array of objects.
8
+ - `field` (string, required): The name of the field to read in each item. It is evaluated.
9
+ - `path` (string, required): The location receiving the array (template syntax).
10
+
11
+ ## Behavior
12
+
13
+ - The array of the `field` values is written at `path`, in the order of the collection.
14
+ - The items that are not objects, and the items whose field is `null`, `undefined` or an empty string, are skipped.
15
+ - A collection that is not an array writes an empty array.
16
+ - The collection is read from the complete data, even inside a `DataFilter`.
17
+
18
+ ## Example
19
+
20
+ ### Select all / deselect all
21
+
22
+ ```yaml
23
+ renderView:
24
+ - type: button
25
+ content: "Select all"
26
+ actions:
27
+ - what: collectField
28
+ on: click
29
+ from: ~~.results
30
+ field: nid
31
+ path: ~~.selection
32
+ - type: button
33
+ content: "Deselect all"
34
+ actions:
35
+ - what: setData
36
+ on: click
37
+ path: ~~.selection
38
+ value: []
39
+
40
+ data:
41
+ results:
42
+ - nid: 4
43
+ title: "First"
44
+ - nid: 9
45
+ title: "Second"
46
+ selection: []
47
+ ```
48
+
49
+ ## Limitations
50
+
51
+ - Only a direct field of the items is read (no nested path such as `author.id`).
@@ -0,0 +1,81 @@
1
+ renderView:
2
+ - type: Markdown
3
+ content: |
4
+ # Reaction: collectField
5
+
6
+ The `collectField` reaction writes the values of one field of every item of a collection, as an array. Typical use: a "select all" checkbox that writes the identifiers of the listed items.
7
+
8
+ ## Properties
9
+
10
+ - type: DefinitionList
11
+ content:
12
+ - term:
13
+ code: from
14
+ after: "(string, required)"
15
+ details: "The collection (template syntax), an array of objects."
16
+ - term:
17
+ code: field
18
+ after: "(string, required)"
19
+ details: "The name of the field to read in each item. It is evaluated."
20
+ - term:
21
+ code: path
22
+ after: "(string, required)"
23
+ details: "The location receiving the array (template syntax)."
24
+
25
+ - type: Markdown
26
+ content: |
27
+ ## Behavior
28
+
29
+ - The array of the `field` values is written at `path`, in the order of the collection.
30
+ - The items that are not objects, and the items whose field is `null`, `undefined` or an empty string, are skipped.
31
+ - A collection that is not an array writes an empty array.
32
+ - The collection is read from the complete data, even inside a `DataFilter`.
33
+
34
+ - type: RjBuildDescriber
35
+ title: "Select all / deselect all"
36
+ description: "collectField writes every nid of the results; setData empties the selection."
37
+ toDescribe:
38
+ renderView:
39
+ - type: button
40
+ attributes:
41
+ type: button
42
+ style:
43
+ marginRight: "0.5rem"
44
+ content: "Select all"
45
+ actions:
46
+ - what: collectField
47
+ on: click
48
+ from: ~~.results
49
+ field: nid
50
+ path: ~~.selection
51
+ - type: button
52
+ attributes:
53
+ type: button
54
+ content: "Deselect all"
55
+ actions:
56
+ - what: setData
57
+ on: click
58
+ path: ~~.selection
59
+ value: []
60
+ - type: div
61
+ content:
62
+ - type: strong
63
+ content: "Selection: "
64
+ - type: Join
65
+ content: ~~.selection
66
+ separator: ", "
67
+ data:
68
+ results:
69
+ - nid: 4
70
+ title: "First"
71
+ - nid: 9
72
+ title: "Second"
73
+ - nid: 15
74
+ title: "Third"
75
+ selection: []
76
+
77
+ - type: Markdown
78
+ content: |
79
+ ## Limitations
80
+
81
+ - Only a direct field of the items is read (no nested path such as `author.id`).
@@ -14,7 +14,7 @@
14
14
  - `requestKey` (string, optional): Identifier used to group requests that should cancel each other. When set, firing a new request with the same key aborts the previous one client-side (via AbortController). Different keys are independent. Bypasses the global lock automatically. See [Concurrency control](#concurrency-control--requestkey) below.
15
15
  - `updateOnlyData` (boolean, optional): When true and `refreshAppOnResponse` is true, only updates the data section instead of replacing the entire RjBuild. Preserves templates and renderView. Default: false.
16
16
  - `updateDataAtLocation` (string, optional): When `updateOnlyData` is true, specifies where to place the response data using template path syntax (e.g., "~~.userProfile", "~.config.settings"). If not specified, replaces the entire data object.
17
- - `url` (string, required): The URL to call (must be a static string, dynamic URLs are not supported)
17
+ - `url` (string or array, required): The URL to call: a string or a template reference (`~~.endpoint`), or an array of segments built like the `src` of `additionalDataSource` (literal strings, references evaluated in the current template context, `{segment, required}`, `{param, value, required}`). No request is sent when the URL is empty, or when a required segment is empty. See [Dynamic URLs with `src` as Array](../../getting-started/rjbuild-structure.md#dynamic-urls-with-src-as-array).
18
18
 
19
19
  ## Behavior
20
20
  - Supports configurable HTTP methods (GET by default for backward compatibility)
@@ -232,6 +232,26 @@ actions:
232
232
  refreshAppOnResponse: false
233
233
  ```
234
234
 
235
+ ### URL built from the data
236
+
237
+ ```yaml
238
+ - type: button
239
+ content: "Load"
240
+ actions:
241
+ - what: fetchData
242
+ on: click
243
+ url:
244
+ - "/api/items/"
245
+ - segment: ~.id
246
+ required: true
247
+ - param: display
248
+ value: ~~.display
249
+ updateOnlyData: true
250
+ updateDataAtLocation: ~~.details
251
+ ```
252
+
253
+ Inside a `Switch` item, `~.id` reads the item: each button loads its own item. Nothing is fetched when the item has no `id`.
254
+
235
255
  ## Limitations
236
256
  - Only one request can be active at a time
237
257
  - Response must be a valid rjbuild **only** if refreshAppOnResponse is true and updateOnlyData is false
@@ -52,10 +52,10 @@ renderView:
52
52
  content: "When true and `refreshAppOnResponse` is true, only updates the data section instead of replacing the entire RjBuild. Preserves templates and renderView. Default: false"
53
53
  - term:
54
54
  code: url
55
- after: "(string, required)"
55
+ after: "(string or array, required)"
56
56
  details:
57
57
  type: Markdown
58
- content: "The URL to call (must be a static string, dynamic URLs are not supported)"
58
+ content: "The URL to call: a string or a template reference (`~~.endpoint`), or an array of segments built like the `src` of `additionalDataSource` (literal strings, references evaluated in the current template context, `{segment, required}`, `{param, value, required}`). No request is sent when the URL is empty, or when a required segment is empty."
59
59
 
60
60
  - type: Markdown
61
61
  content: |
@@ -11,6 +11,10 @@ Reactions in Reactive-JSON allow you to respond to user events and perform opera
11
11
  - **[addData](./addData.md)**: Adds new data to the specified path
12
12
  - **[removeData](./removeData.md)**: Removes data from the specified path
13
13
  - **[moveData](./moveData.md)**: Moves data from one path to another
14
+ - **[toggleData](./toggleData.md)**: Adds a value to an array when absent, removes it when present
15
+ - **[collectField](./collectField.md)**: Writes the values of a field of every item of a collection as an array
16
+ - **[joinData](./joinData.md)**: Writes a string built from several parts (literals, references, segments)
17
+ - **[stringifyData](./stringifyData.md)**: Writes the JSON representation of a value
14
18
 
15
19
  ### Network Operations
16
20
  - **[fetchData](./fetchData.md)**: Fetches data from a URL using GET requests
@@ -21,4 +25,5 @@ Reactions in Reactive-JSON allow you to respond to user events and perform opera
21
25
  - **[redirectNow](./redirectNow.md)**: Performs an immediate redirect
22
26
  - **[triggerEvent](./triggerEvent.md)**: Triggers a custom event
23
27
  - **[postMessage](./postMessage.md)**: Sends a message to another window/frame
28
+ - **[printPage](./printPage.md)**: Opens the print dialog of the browser
24
29
 
@@ -14,6 +14,10 @@ renderView:
14
14
  - **[addData](./addData)**: Adds new data to the specified path
15
15
  - **[removeData](./removeData)**: Removes data from the specified path
16
16
  - **[moveData](./moveData)**: Moves data from one path to another
17
+ - **[toggleData](./toggleData)**: Adds a value to an array when absent, removes it when present
18
+ - **[collectField](./collectField)**: Writes the values of a field of every item of a collection as an array
19
+ - **[joinData](./joinData)**: Writes a string built from several parts (literals, references, segments)
20
+ - **[stringifyData](./stringifyData)**: Writes the JSON representation of a value
17
21
 
18
22
  ### Network Operations
19
23
  - **[fetchData](./fetchData)**: Fetches data from a URL using GET requests
@@ -24,3 +28,4 @@ renderView:
24
28
  - **[redirectNow](./redirectNow)**: Performs an immediate redirect
25
29
  - **[triggerEvent](./triggerEvent)**: Triggers a custom event
26
30
  - **[postMessage](./postMessage)**: Sends a message to another window/frame
31
+ - **[printPage](./printPage)**: Opens the print dialog of the browser