@ea-lab/reactive-json-docs 2.8.0 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/package.json +2 -2
  2. package/public/rjbuild/docs/core/element/form/CheckBoxField.md +142 -18
  3. package/public/rjbuild/docs/core/element/form/CheckBoxField.yaml +132 -7
  4. package/public/rjbuild/docs/core/element/form/SelectField.md +36 -10
  5. package/public/rjbuild/docs/core/element/form/SelectField.yaml +37 -3
  6. package/public/rjbuild/docs/core/element/form/formElementsCommon.md +32 -0
  7. package/public/rjbuild/docs/core/element/html/Html.yaml +47 -0
  8. package/public/rjbuild/docs/core/element/html/LabelFromValue.md +159 -0
  9. package/public/rjbuild/docs/core/element/html/LabelFromValue.yaml +163 -10
  10. package/public/rjbuild/docs/core/element/special/DataSync.md +41 -1
  11. package/public/rjbuild/docs/core/element/special/DataSync.yaml +41 -1
  12. package/public/rjbuild/docs/core/example/native-html-forms.md +19 -2
  13. package/public/rjbuild/docs/core/hook/index.md +3 -0
  14. package/public/rjbuild/docs/core/hook/index.yaml +3 -0
  15. package/public/rjbuild/docs/core/reaction/collectField.md +51 -0
  16. package/public/rjbuild/docs/core/reaction/collectField.yaml +81 -0
  17. package/public/rjbuild/docs/core/reaction/fetchData.md +21 -1
  18. package/public/rjbuild/docs/core/reaction/fetchData.yaml +2 -2
  19. package/public/rjbuild/docs/core/reaction/index.md +5 -0
  20. package/public/rjbuild/docs/core/reaction/index.yaml +5 -0
  21. package/public/rjbuild/docs/core/reaction/joinData.md +51 -0
  22. package/public/rjbuild/docs/core/reaction/joinData.yaml +87 -0
  23. package/public/rjbuild/docs/core/reaction/printPage.md +22 -0
  24. package/public/rjbuild/docs/core/reaction/printPage.yaml +29 -0
  25. package/public/rjbuild/docs/core/reaction/redirectNow.md +20 -2
  26. package/public/rjbuild/docs/core/reaction/redirectNow.yaml +24 -3
  27. package/public/rjbuild/docs/core/reaction/setClipboardData.md +35 -6
  28. package/public/rjbuild/docs/core/reaction/setClipboardData.yaml +18 -6
  29. package/public/rjbuild/docs/core/reaction/stringifyData.md +45 -0
  30. package/public/rjbuild/docs/core/reaction/stringifyData.yaml +58 -0
  31. package/public/rjbuild/docs/core/reaction/submitData.md +1 -1
  32. package/public/rjbuild/docs/core/reaction/submitData.yaml +4 -2
  33. package/public/rjbuild/docs/core/reaction/toggleData.md +72 -0
  34. package/public/rjbuild/docs/core/reaction/toggleData.yaml +77 -0
  35. package/public/rjbuild/docs/getting-started/reactions.md +5 -0
  36. package/public/rjbuild/docs/getting-started/reactions.yaml +5 -0
  37. package/public/rjbuild/docs/getting-started/rjbuild-structure.md +23 -1
  38. package/public/rjbuild/docs/getting-started/rjbuild-structure.yaml +25 -1
@@ -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
@@ -0,0 +1,51 @@
1
+ # Reaction: joinData
2
+
3
+ The `joinData` reaction writes a string built from several parts at a location: a URL that depends on the data, a label, a key. YAML has no string concatenation; `joinData` fills this gap.
4
+
5
+ ## Properties
6
+
7
+ - `path` (string, required): The location receiving the string (template syntax).
8
+ - `parts` (array, required): The parts of the string, in the format of the `src` of `additionalDataSource` (see [Dynamic URLs with `src` as Array](../../getting-started/rjbuild-structure.md#dynamic-urls-with-src-as-array)):
9
+ - a literal string;
10
+ - a template reference (`~.slug`, `~~.id`, `~>item.id`), evaluated in the current template context;
11
+ - `{segment, required}`: a reference used as a path part;
12
+ - `{param, value, required}`: a query parameter, appended after the path (`?key=value`, or `&key=value` when the path already has a query string).
13
+
14
+ ## Behavior
15
+
16
+ - An empty reference adds an empty string.
17
+ - An empty `required` segment or parameter cancels the write: the location keeps its value. Mark the parts that must never be missing as required, to avoid writing a truncated URL.
18
+ - A non-required parameter whose key or value is empty is omitted.
19
+
20
+ ## Example
21
+
22
+ ### Build the URL of the chosen entity, then submit to it
23
+
24
+ ```yaml
25
+ renderView:
26
+ - type: button
27
+ content: "Link"
28
+ actions:
29
+ - what: joinData
30
+ on: click
31
+ path: ~~.saveUrl
32
+ parts:
33
+ - "/api/save?bundle=company&id="
34
+ - segment: ~~.selectedId
35
+ required: true
36
+ - what: submitData
37
+ on: click
38
+ url: ~~.saveUrl
39
+ data:
40
+ parent: ~~.parentId
41
+
42
+ data:
43
+ selectedId: 42
44
+ parentId: 7
45
+ ```
46
+
47
+ `fetchData`, `submitData` and `redirectNow` also accept the parts directly in `url` / `to`, and URL attributes (`href`, `src`...) accept them too: use `joinData` when the composed string must be stored, or shown.
48
+
49
+ ## Limitations
50
+
51
+ - The parts are joined as they are: path parts are not URL-encoded (only parameters are).
@@ -0,0 +1,87 @@
1
+ renderView:
2
+ - type: Markdown
3
+ content: |
4
+ # Reaction: joinData
5
+
6
+ The `joinData` reaction writes a string built from several parts at a location: a URL that depends on the data, a label, a key. YAML has no string concatenation; `joinData` fills this gap.
7
+
8
+ ## Properties
9
+
10
+ - type: DefinitionList
11
+ content:
12
+ - term:
13
+ code: path
14
+ after: "(string, required)"
15
+ details: "The location receiving the string (template syntax)."
16
+ - term:
17
+ code: parts
18
+ after: "(array, required)"
19
+ details:
20
+ type: Markdown
21
+ content: |
22
+ The parts of the string, in the format of the `src` of `additionalDataSource` (see *Dynamic URLs with `src` as Array* in [RjBuild structure](../../getting-started/rjbuild-structure)):
23
+ - a literal string;
24
+ - a template reference (`~.slug`, `~~.id`, `~>item.id`), evaluated in the current template context;
25
+ - `{segment, required}`: a reference used as a path part;
26
+ - `{param, value, required}`: a query parameter, appended after the path (`?key=value`, or `&key=value` when the path already has a query string).
27
+
28
+ - type: Markdown
29
+ content: |
30
+ ## Behavior
31
+
32
+ - An empty reference adds an empty string.
33
+ - An empty `required` segment or parameter cancels the write: the location keeps its value. Mark the parts that must never be missing as required, to avoid writing a truncated URL.
34
+ - A non-required parameter whose key or value is empty is omitted.
35
+
36
+ - type: RjBuildDescriber
37
+ title: "Compose a URL per item"
38
+ description: "Each button writes the URL of its item; the required segment prevents a truncated URL."
39
+ toDescribe:
40
+ renderView:
41
+ - type: Switch
42
+ content: ~~.articles
43
+ singleOption:
44
+ load: article
45
+ - type: div
46
+ content:
47
+ - type: strong
48
+ content: "URL: "
49
+ - type: code
50
+ content: ~~.url
51
+ templates:
52
+ article:
53
+ type: button
54
+ attributes:
55
+ type: button
56
+ style:
57
+ marginRight: "0.5rem"
58
+ content: ~.title
59
+ actions:
60
+ - what: joinData
61
+ on: click
62
+ path: ~~.url
63
+ parts:
64
+ - "/article/"
65
+ - ~.year
66
+ - "/"
67
+ - segment: ~.slug
68
+ required: true
69
+ - param: lang
70
+ value: ~~.lang
71
+ data:
72
+ lang: "fr"
73
+ url: ""
74
+ articles:
75
+ - title: "With a slug"
76
+ year: 2026
77
+ slug: "hello"
78
+ - title: "Without a slug"
79
+ year: 2025
80
+
81
+ - type: Markdown
82
+ content: |
83
+ `fetchData`, `submitData` and `redirectNow` also accept the parts directly in `url` / `to`, and URL attributes (`href`, `src`...) accept them too: use `joinData` when the composed string must be stored, or shown.
84
+
85
+ ## Limitations
86
+
87
+ - The parts are joined as they are: path parts are not URL-encoded (only parameters are).
@@ -0,0 +1,22 @@
1
+ # Reaction: printPage
2
+
3
+ The `printPage` reaction opens the print dialog of the browser for the current page (`window.print()`).
4
+
5
+ ## Properties
6
+
7
+ This reaction has no specific property.
8
+
9
+ ## Example
10
+
11
+ ```yaml
12
+ renderView:
13
+ - type: button
14
+ content: "Print"
15
+ actions:
16
+ - what: printPage
17
+ on: click
18
+ ```
19
+
20
+ ## Limitations
21
+
22
+ - The whole page is printed: use print CSS (`@media print`) to hide the parts that must not be printed.
@@ -0,0 +1,29 @@
1
+ renderView:
2
+ - type: Markdown
3
+ content: |
4
+ # Reaction: printPage
5
+
6
+ The `printPage` reaction opens the print dialog of the browser for the current page (`window.print()`).
7
+
8
+ ## Properties
9
+
10
+ This reaction has no specific property.
11
+
12
+ - type: RjBuildDescriber
13
+ title: "Print button"
14
+ description: "Clicking the button opens the print dialog."
15
+ toDescribe:
16
+ renderView:
17
+ - type: button
18
+ attributes:
19
+ type: button
20
+ content: "Print"
21
+ actions:
22
+ - what: printPage
23
+ on: click
24
+
25
+ - type: Markdown
26
+ content: |
27
+ ## Limitations
28
+
29
+ - The whole page is printed: use print CSS (`@media print`) to hide the parts that must not be printed.
@@ -4,12 +4,14 @@ The `redirectNow` reaction performs an immediate browser redirection to a specif
4
4
 
5
5
  ## Properties
6
6
 
7
- - `to` (string, required): The URL to redirect to. This value is evaluated, so it can be a static URL or dynamically constructed from data.
7
+ - `to` (string or array, required): The URL to redirect to: a string or a template reference, 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}`). See [Dynamic URLs with `src` as Array](../../getting-started/rjbuild-structure.md#dynamic-urls-with-src-as-array).
8
+ - `replace` (boolean, optional): When `true`, the current history entry is replaced instead of adding a new one (the back button does not come back to the current page). Default: `false`.
8
9
 
9
10
  ## Behavior
10
11
 
11
12
  - When triggered, the reaction evaluates the `to` property to get the target URL.
12
- - It then sets `window.location.href` to the resulting URL, causing the browser to navigate to the new page.
13
+ - It then sets `window.location.href` to the resulting URL (or calls `window.location.replace()` with `replace: true`), causing the browser to navigate to the new page.
14
+ - Nothing happens when the URL is empty, or when a required segment is empty: the user is never sent to a truncated URL.
13
15
 
14
16
  ## Example
15
17
 
@@ -27,6 +29,22 @@ renderView:
27
29
  to: "https://github.com/reactive-json/reactive-json"
28
30
  ```
29
31
 
32
+ ### Redirecting to a URL built from a response
33
+
34
+ After a creation, the URL of the new item is only known from the response:
35
+
36
+ ```yaml
37
+ - what: redirectNow
38
+ on: response
39
+ replace: true
40
+ to:
41
+ - "/dashboards/"
42
+ - segment: "<reactive-json:event-new-value>.id"
43
+ required: true
44
+ - param: edit
45
+ value: "1"
46
+ ```
47
+
30
48
  ## Limitations
31
49
 
32
50
  - The `to` property must resolve to a valid URL string for the redirection to work.
@@ -11,17 +11,38 @@ renderView:
11
11
  content:
12
12
  - term:
13
13
  code: to
14
- after: "(string, required)"
14
+ after: "(string or array, required)"
15
15
  details:
16
16
  type: Markdown
17
- content: "The URL to redirect to. This value is evaluated, so it can be a static URL or dynamically constructed from data"
17
+ content: "The URL to redirect to: a string or a template reference, 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}`). See *Dynamic URLs with `src` as Array* in [RjBuild structure](../../getting-started/rjbuild-structure)."
18
+ - term:
19
+ code: replace
20
+ after: "(boolean, optional)"
21
+ details: "When true, the current history entry is replaced instead of adding a new one (the back button does not come back to the current page). Default: false."
18
22
 
19
23
  - type: Markdown
20
24
  content: |
21
25
  ## Behavior
22
26
 
23
27
  - When triggered, the reaction evaluates the `to` property to get the target URL.
24
- - It then sets `window.location.href` to the resulting URL, causing the browser to navigate to the new page.
28
+ - It then sets `window.location.href` to the resulting URL (or calls `window.location.replace()` with `replace: true`), causing the browser to navigate to the new page.
29
+ - Nothing happens when the URL is empty, or when a required segment is empty: the user is never sent to a truncated URL.
30
+
31
+ ## URL built from a response
32
+
33
+ After a creation, the URL of the new item is only known from the response:
34
+
35
+ ```yaml
36
+ - what: redirectNow
37
+ on: response
38
+ replace: true
39
+ to:
40
+ - "/dashboards/"
41
+ - segment: "<reactive-json:event-new-value>.id"
42
+ required: true
43
+ - param: edit
44
+ value: "1"
45
+ ```
25
46
 
26
47
  ## Limitations
27
48
 
@@ -5,13 +5,14 @@ The `setClipboardData` reaction copies a specified value to the user's clipboard
5
5
  ## Properties
6
6
 
7
7
  - `value` (any, required): The value to be copied to the clipboard. The value is evaluated, so it can be a literal string or a path to data.
8
+ - `statusPath` (string, optional): A location receiving `"copied"` or `"failed"` once the copy is done, so that the page can react to the outcome (show a confirmation, announce it with a notice...).
8
9
 
9
10
  ## Behavior
10
11
 
11
12
  - When triggered, the reaction evaluates the `value` property.
12
- - If the evaluated value is a string, it uses the `navigator.clipboard.writeText()` API to copy it to the clipboard.
13
- - If the evaluated value is not a string, the reaction does nothing.
14
- - An error is logged to the console if the clipboard operation fails (e.g., due to browser permissions).
13
+ - A string or a number is copied with the `navigator.clipboard.writeText()` API. Other values (objects, arrays) and empty values are ignored.
14
+ - Outside a secure context (plain http on a host other than `localhost`), where the Clipboard API is not available, or when it fails, the copy falls back to the deprecated `copy` command on a temporary text field.
15
+ - An error is logged to the console if the copy fails, and `statusPath` receives `"failed"`. A value that cannot be copied (empty, object, array) also reports `"failed"`.
15
16
 
16
17
  ## Example
17
18
 
@@ -22,7 +23,7 @@ This example shows a button that, when clicked, copies the value of `~.shareable
22
23
  ```yaml
23
24
  renderView:
24
25
  - type: div
25
- content: "Your code: ~.shareable_code"
26
+ content: ["Your code: ", ~.shareable_code]
26
27
  - type: button
27
28
  content: "Copy Code"
28
29
  actions:
@@ -33,8 +34,36 @@ data:
33
34
  shareable_code: "ABC-123-XYZ"
34
35
  ```
35
36
 
37
+ ### Showing the outcome
38
+
39
+ ```yaml
40
+ renderView:
41
+ - type: button
42
+ content: "Copy the key"
43
+ actions:
44
+ - what: setClipboardData
45
+ on: click
46
+ value: ~~.apiKey
47
+ statusPath: ~~.copyStatus
48
+ - type: span
49
+ content: "Copied"
50
+ actions:
51
+ - what: hide
52
+ when: ~~.copyStatus
53
+ isNot: "copied"
54
+ - type: span
55
+ content: "The copy failed: select the key and copy it manually."
56
+ actions:
57
+ - what: hide
58
+ when: ~~.copyStatus
59
+ isNot: "failed"
60
+
61
+ data:
62
+ apiKey: "ABC-123-XYZ"
63
+ copyStatus: ""
64
+ ```
65
+
36
66
  ## Limitations
37
67
 
38
- - This reaction relies on the Clipboard API, which requires a secure context (HTTPS) to function in most modern browsers.
39
68
  - The user may be prompted for permission to access the clipboard, depending on browser settings.
40
- - The reaction only supports copying string values. Numbers and other types will be converted to strings, but objects and arrays will not be copied.
69
+ - Only strings and numbers are copied: objects and arrays are ignored.
@@ -15,21 +15,26 @@ renderView:
15
15
  details:
16
16
  type: Markdown
17
17
  content: "The value to be copied to the clipboard. The value is evaluated, so it can be a literal string or a path to data"
18
+ - term:
19
+ code: statusPath
20
+ after: "(string, optional)"
21
+ details:
22
+ type: Markdown
23
+ content: "A location receiving `\"copied\"` or `\"failed\"` once the copy is done, so that the page can react to the outcome."
18
24
 
19
25
  - type: Markdown
20
26
  content: |
21
27
  ## Behavior
22
28
 
23
29
  - When triggered, the reaction evaluates the `value` property.
24
- - If the evaluated value is a string, it uses the `navigator.clipboard.writeText()` API to copy it to the clipboard.
25
- - If the evaluated value is not a string, the reaction does nothing.
26
- - An error is logged to the console if the clipboard operation fails (e.g., due to browser permissions).
30
+ - A string or a number is copied with the `navigator.clipboard.writeText()` API. Other values (objects, arrays) and empty values are ignored.
31
+ - Outside a secure context (plain http on a host other than `localhost`), where the Clipboard API is not available, or when it fails, the copy falls back to the deprecated `copy` command on a temporary text field.
32
+ - An error is logged to the console if the copy fails, and `statusPath` receives `"failed"`. A value that cannot be copied (empty, object, array) also reports `"failed"`.
27
33
 
28
34
  ## Limitations
29
35
 
30
- - This reaction relies on the Clipboard API, which requires a secure context (HTTPS) to function in most modern browsers.
31
36
  - The user may be prompted for permission to access the clipboard, depending on browser settings.
32
- - The reaction only supports copying string values. Numbers and other types will be converted to strings, but objects and arrays will not be copied.
37
+ - Only strings and numbers are copied: objects and arrays are ignored.
33
38
 
34
39
  - type: RjBuildDescriber
35
40
  title: "Copying text to the clipboard"
@@ -44,5 +49,12 @@ renderView:
44
49
  - what: setClipboardData
45
50
  on: click
46
51
  value: ~.shareable_code
52
+ statusPath: ~.copyStatus
53
+ - type: span
54
+ attributes:
55
+ style:
56
+ marginLeft: "0.5rem"
57
+ content: ["Status: ", ~.copyStatus]
47
58
  data:
48
- shareable_code: "ABC-123-XYZ"
59
+ shareable_code: "ABC-123-XYZ"
60
+ copyStatus: ""
@@ -0,0 +1,45 @@
1
+ # Reaction: stringifyData
2
+
3
+ The `stringifyData` reaction writes the JSON representation of a value (`JSON.stringify`) at a location. Use it to send structured data (an array, an object) to an endpoint that expects a text field.
4
+
5
+ ## Properties
6
+
7
+ - `from` (string, required): The value to serialize (template syntax).
8
+ - `path` (string, required): The location receiving the JSON string (template syntax).
9
+
10
+ ## Behavior
11
+
12
+ - The JSON string is written synchronously, in the order of the actions list. Placed before a `submitData` of the same event, it guarantees that the submitted data holds the fresh JSON.
13
+ - An undefined value writes an empty string.
14
+ - The value is read from the complete data, even inside a `DataFilter`.
15
+
16
+ ## Example
17
+
18
+ ### Save a layout as JSON
19
+
20
+ ```yaml
21
+ renderView:
22
+ - type: button
23
+ content: "Save"
24
+ actions:
25
+ - what: stringifyData
26
+ on: click
27
+ from: ~~.dashboard.widgets
28
+ path: ~~.dashboard.payload.layout
29
+ - what: submitData
30
+ on: click
31
+ url: "/api/dashboard/save"
32
+ data:
33
+ layout: ~~.dashboard.payload.layout
34
+
35
+ data:
36
+ dashboard:
37
+ widgets:
38
+ - id: "sales"
39
+ width: 2
40
+ payload: {}
41
+ ```
42
+
43
+ ## Limitations
44
+
45
+ - The JSON is compact (no indentation).
@@ -0,0 +1,58 @@
1
+ renderView:
2
+ - type: Markdown
3
+ content: |
4
+ # Reaction: stringifyData
5
+
6
+ The `stringifyData` reaction writes the JSON representation of a value (`JSON.stringify`) at a location. Use it to send structured data (an array, an object) to an endpoint that expects a text field.
7
+
8
+ ## Properties
9
+
10
+ - type: DefinitionList
11
+ content:
12
+ - term:
13
+ code: from
14
+ after: "(string, required)"
15
+ details: "The value to serialize (template syntax)."
16
+ - term:
17
+ code: path
18
+ after: "(string, required)"
19
+ details: "The location receiving the JSON string (template syntax)."
20
+
21
+ - type: Markdown
22
+ content: |
23
+ ## Behavior
24
+
25
+ - The JSON string is written synchronously, in the order of the actions list. Placed before a `submitData` of the same event, it guarantees that the submitted data holds the fresh JSON.
26
+ - An undefined value writes an empty string.
27
+ - The value is read from the complete data, even inside a `DataFilter`.
28
+
29
+ - type: RjBuildDescriber
30
+ title: "Serialize a list"
31
+ description: "The button writes the JSON of the widgets list in payload.layout."
32
+ toDescribe:
33
+ renderView:
34
+ - type: button
35
+ attributes:
36
+ type: button
37
+ content: "Serialize"
38
+ actions:
39
+ - what: stringifyData
40
+ on: click
41
+ from: ~~.widgets
42
+ path: ~~.payload.layout
43
+ - type: pre
44
+ content: ~~.payload.layout
45
+ data:
46
+ widgets:
47
+ - id: "sales"
48
+ width: 2
49
+ - id: "leads"
50
+ width: 1
51
+ payload:
52
+ layout: ""
53
+
54
+ - type: Markdown
55
+ content: |
56
+ ## Limitations
57
+
58
+ - The JSON is compact (no indentation).