@lowdefy/docs-content 0.0.0-experimental-20260928120643 → 6.1.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/README.md +0 -1
- package/content/actions/link.md +0 -17
- package/content/actions/login.md +5 -23
- package/content/actions/logout.md +5 -5
- package/content/actions/pdfmake.md +2 -2
- package/content/actions/setdarkmode.md +2 -2
- package/content/agents/agent-properties.md +2 -4
- package/content/agents/agentchat.md +6 -21
- package/content/agents/agentconversations.md +2 -2
- package/content/concepts/ai-agent-docs.md +101 -313
- package/content/concepts/cli.md +3 -34
- package/content/concepts/connections-and-requests.md +0 -402
- package/content/concepts/custom-html.md +0 -40
- package/content/concepts/custom-styling.md +5 -50
- package/content/concepts/events-and-actions.md +2 -64
- package/content/concepts/i18n.md +2 -7
- package/content/concepts/keyboard-shortcuts.md +2 -2
- package/content/concepts/layout-overview.md +1 -1
- package/content/concepts/logger.md +0 -81
- package/content/concepts/lowdefy-schema.md +1 -4
- package/content/concepts/menus.md +7 -7
- package/content/concepts/module-authoring.md +2 -2
- package/content/connections/anthropic.md +2 -162
- package/content/connections/awss3.md +0 -54
- package/content/connections/google.md +2 -162
- package/content/connections/mongodb.md +3 -121
- package/content/connections/openai-connection.md +2 -162
- package/content/container-blocks/affix.md +7 -47
- package/content/container-blocks/alert.md +24 -76
- package/content/container-blocks/badge.md +24 -100
- package/content/container-blocks/box.md +9 -9
- package/content/container-blocks/card.md +25 -80
- package/content/container-blocks/carousel.md +7 -60
- package/content/container-blocks/collapse.md +9 -87
- package/content/container-blocks/configprovider.md +13 -35
- package/content/container-blocks/confirmmodal.md +23 -69
- package/content/container-blocks/content.md +98 -62
- package/content/container-blocks/descriptions.md +4 -45
- package/content/container-blocks/drawer.md +28 -92
- package/content/container-blocks/dropdownmenu.md +31 -119
- package/content/container-blocks/flex.md +62 -40
- package/content/container-blocks/footer.md +11 -15
- package/content/container-blocks/googlemapsheatmap.md +1 -1
- package/content/container-blocks/googlemapsscript.md +2 -2
- package/content/container-blocks/header.md +36 -71
- package/content/container-blocks/label.md +7 -34
- package/content/container-blocks/layout.md +34 -52
- package/content/container-blocks/masonry.md +71 -17
- package/content/container-blocks/mobilemenu.md +88 -131
- package/content/container-blocks/modal.md +26 -114
- package/content/container-blocks/pageheadermenu.md +31 -81
- package/content/container-blocks/pagesidebarlayout.md +26 -169
- package/content/container-blocks/pagesidermenu.md +42 -95
- package/content/container-blocks/popover.md +31 -34
- package/content/container-blocks/result.md +21 -32
- package/content/container-blocks/sider.md +122 -85
- package/content/container-blocks/span.md +7 -7
- package/content/container-blocks/spinner.md +3 -3
- package/content/container-blocks/splitter.md +68 -150
- package/content/container-blocks/tabs.md +12 -64
- package/content/container-blocks/tooltip.md +46 -22
- package/content/container-blocks/watermark.md +4 -22
- package/content/controls/reject.md +2 -4
- package/content/controls/throw.md +0 -1
- package/content/controls/try.md +2 -3
- package/content/deployment/deployment-environments.md +6 -8
- package/content/deployment/docker.md +7 -22
- package/content/deployment/node-server.md +0 -4
- package/content/deployment/vercel.md +6 -13
- package/content/display-blocks/aggrid.md +11 -26
- package/content/display-blocks/anchor.md +15 -15
- package/content/display-blocks/avatar.md +37 -57
- package/content/display-blocks/breadcrumb.md +21 -70
- package/content/display-blocks/button.md +18 -92
- package/content/display-blocks/calendar.md +0 -12
- package/content/display-blocks/dangeroushtml.md +1 -1
- package/content/display-blocks/difflist.md +1 -1
- package/content/display-blocks/difftimeline.md +1 -1
- package/content/display-blocks/divider.md +3 -64
- package/content/display-blocks/dropdownbutton.md +28 -79
- package/content/display-blocks/echart.md +1 -35
- package/content/display-blocks/floatbutton.md +42 -129
- package/content/display-blocks/html.md +1 -61
- package/content/display-blocks/icon.md +67 -250
- package/content/display-blocks/menu.md +73 -145
- package/content/display-blocks/message.md +124 -38
- package/content/display-blocks/notification.md +222 -94
- package/content/display-blocks/paragraph.md +9 -59
- package/content/display-blocks/progress.md +17 -96
- package/content/display-blocks/qrcode.md +4 -19
- package/content/display-blocks/s3download.md +1 -1
- package/content/display-blocks/search.md +7 -17
- package/content/display-blocks/skeletonbutton.md +0 -1
- package/content/display-blocks/skeletoninput.md +0 -1
- package/content/display-blocks/statistic.md +17 -75
- package/content/display-blocks/steps.md +25 -58
- package/content/display-blocks/tag.md +17 -102
- package/content/display-blocks/title.md +11 -50
- package/content/display-blocks/tour.md +23 -33
- package/content/input-blocks/autocomplete.md +9 -81
- package/content/input-blocks/buttonselector.md +8 -45
- package/content/input-blocks/checkboxselector.md +7 -97
- package/content/input-blocks/checkboxswitch.md +3 -33
- package/content/input-blocks/colorselector.md +14 -63
- package/content/input-blocks/daterangeselector.md +45 -165
- package/content/input-blocks/dateselector.md +41 -139
- package/content/input-blocks/datetimeselector.md +49 -158
- package/content/input-blocks/inputgallery.md +3 -3
- package/content/input-blocks/monthselector.md +52 -120
- package/content/input-blocks/multipleselector.md +39 -150
- package/content/input-blocks/numberinput.md +12 -98
- package/content/input-blocks/pagination.md +14 -70
- package/content/input-blocks/paragraphinput.md +37 -51
- package/content/input-blocks/passwordinput.md +6 -60
- package/content/input-blocks/phonenumberinput.md +26 -59
- package/content/input-blocks/radioselector.md +7 -83
- package/content/input-blocks/ratingslider.md +26 -57
- package/content/input-blocks/s3uploadbutton.md +24 -24
- package/content/input-blocks/s3uploaddragger.md +3 -3
- package/content/input-blocks/s3uploadphoto.md +5 -5
- package/content/input-blocks/segmentedselector.md +32 -72
- package/content/input-blocks/selector.md +21 -109
- package/content/input-blocks/switch.md +17 -65
- package/content/input-blocks/textarea.md +3 -32
- package/content/input-blocks/textinput.md +28 -69
- package/content/input-blocks/tiptapmentioninput.md +1 -1
- package/content/input-blocks/titleinput.md +12 -39
- package/content/input-blocks/treeinput.md +25 -49
- package/content/input-blocks/treemultipleselector.md +10 -127
- package/content/input-blocks/treeselector.md +9 -97
- package/content/input-blocks/upload.md +15 -64
- package/content/input-blocks/uploaddragger.md +1 -17
- package/content/input-blocks/uploadphoto.md +1 -18
- package/content/input-blocks/weekselector.md +55 -120
- package/content/list-blocks/controlledlist.md +15 -24
- package/content/list-blocks/list.md +11 -11
- package/content/list-blocks/masonrylist.md +34 -7
- package/content/migration/upgrade-guide.md +0 -1
- package/content/operators/_app.md +1 -2
- package/content/operators/_error.md +1 -23
- package/content/operators/_get.md +6 -6
- package/content/operators/_operator.md +3 -17
- package/content/operators/_ref.md +0 -258
- package/content/operators/_type.md +3 -14
- package/content/operators/_user.md +3 -3
- package/content/other/introduction.md +1 -1
- package/content/plugins/plugins-dev.md +0 -66
- package/content/plugins/plugins-introduction.md +1 -27
- package/content/testing/e2e-configuration.md +1 -8
- package/content/testing/e2e-getting-started.md +1 -1
- package/content/testing/e2e-introduction.md +1 -1
- package/content/tutorial/tutorial-actions-operators.md +2 -2
- package/content/tutorial/tutorial-add-blocks.md +2 -2
- package/content/tutorial/tutorial-create-page.md +2 -48
- package/content/tutorial/tutorial-display-data-page.md +3 -3
- package/content/tutorial/tutorial-requests-sql.md +0 -153
- package/content/tutorial/tutorial-start.md +1 -66
- package/content/user-authentication/login-and-logout.md +8 -158
- package/content/user-authentication/users-introduction.md +0 -8
- package/index.json +2 -6065
- package/package.json +1 -7
- package/scripts/extractAgentDocs.js +4 -36
- package/content/actions/emailotpsend.md +0 -58
- package/content/actions/emailotpverify.md +0 -77
- package/content/actions/getlocalstorage.md +0 -41
- package/content/actions/magiclinkverify.md +0 -113
- package/content/actions/posthogalias.md +0 -29
- package/content/actions/posthogcapture.md +0 -49
- package/content/actions/posthogcapturepageleave.md +0 -38
- package/content/actions/posthogfeatureflag.md +0 -50
- package/content/actions/posthoggroup.md +0 -37
- package/content/actions/posthogidentify.md +0 -54
- package/content/actions/posthoginit.md +0 -66
- package/content/actions/posthogoptin.md +0 -29
- package/content/actions/posthogoptout.md +0 -29
- package/content/actions/posthogpageview.md +0 -37
- package/content/actions/posthogreloadfeatureflags.md +0 -47
- package/content/actions/posthogreset.md +0 -28
- package/content/actions/posthogsetpersonproperties.md +0 -36
- package/content/actions/removelocalstorage.md +0 -26
- package/content/actions/setlocalstorage.md +0 -32
- package/content/adapter-reference/mongodbauthadapter.md +0 -46
- package/content/agents/agents-introduction.md +0 -107
- package/content/callback-reference/auth0logoutcallback.md +0 -54
- package/content/concepts/blocks.md +0 -150
- package/content/concepts/dynamic-page-content.md +0 -304
- package/content/concepts/html-attributes.md +0 -285
- package/content/concepts/lowdefy-api.md +0 -1110
- package/content/concepts/notifications.md +0 -155
- package/content/concepts/page-and-app-state.md +0 -244
- package/content/concepts/theming.md +0 -582
- package/content/connections/aigateway.md +0 -368
- package/content/connections/axioshttp.md +0 -181
- package/content/controls/while.md +0 -46
- package/content/display-blocks/clickablehtml.md +0 -239
- package/content/display-blocks/eventlog.md +0 -363
- package/content/display-blocks/pollingtimer.md +0 -263
- package/content/input-blocks/captcha.md +0 -40
- package/content/input-blocks/placesautocomplete.md +0 -319
- package/content/input-blocks/tagmultipleselector.md +0 -114
- package/content/input-blocks/tagselector.md +0 -114
- package/content/migration/auth-upgrade.md +0 -327
- package/content/migration/v3-to-v4.md +0 -417
- package/content/migration/v6-to-v7.md +0 -222
- package/content/operators/_cron.md +0 -292
- package/content/other/mongodbadapter.md +0 -3
- package/content/plugins/plugins-icon-sets.md +0 -267
- package/content/plugins/posthog.md +0 -275
- package/content/provider-reference/auth-js-providers.md +0 -107
- package/content/provider-reference/openidconnectprovider.md +0 -44
- package/content/testing/config-tests.md +0 -278
- package/content/tutorial/tutorial-requests-api.md +0 -155
- package/content/user-authentication/auth-configuration.md +0 -266
- package/content/user-authentication/auth-steps.md +0 -138
- package/content/user-authentication/mcp-oauth.md +0 -292
- package/content/user-authentication/organizations.md +0 -221
- package/content/user-authentication/protected-pages-apis.md +0 -97
- package/content/user-authentication/roles.md +0 -49
- package/content/user-authentication/two-factor.md +0 -229
- package/content/user-authentication/user-object.md +0 -58
- package/content/websockets/websocket-publish.md +0 -108
- package/content/websockets/websocket-subscriptions.md +0 -100
- package/content/websockets/websockets-introduction.md +0 -97
- package/hazards.json +0 -44
- package/scripts/hashDocSources.js +0 -38
- package/scripts/recordSourceHashes.js +0 -88
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
# Notifications
|
|
2
|
-
|
|
3
|
-
Lowdefy can render branded notification emails from config. You define a notification's content once in a `notifications:` section — as a template with interpolated properties — and render it from an API routine with the `RenderNotification` step. Rendering is all the framework does: **storing a notification, deduplicating, sending the email, and tracking delivery are composed in your API routines**, either by hand or with a notifications module.
|
|
4
|
-
|
|
5
|
-
This split is deliberate. Rendering an email safely (turning template properties and data into HTML, with a guarantee that user data can never inject links or markup) and composing link URLs are the two things config alone cannot do, so they live in the framework. Everything else — inserting a record, sending, retrying — is ordinary [requests](/connections-and-requests) and [API routines](/lowdefy-api), which you already have. A consequence worth knowing: because storing is just a request and sending is just a request, notifications work with any database and any email provider Lowdefy connects to.
|
|
6
|
-
|
|
7
|
-
## The `notifications:` section
|
|
8
|
-
|
|
9
|
-
`notifications:` is a root section. Each entry is `{ id, type, properties }`, where **the template is the type**:
|
|
10
|
-
|
|
11
|
-
```yaml
|
|
12
|
-
notifications:
|
|
13
|
-
- id: task-assigned
|
|
14
|
-
type: NotificationEmail
|
|
15
|
-
properties:
|
|
16
|
-
subject: 'New task: {{ task.title }}'
|
|
17
|
-
title: Task assigned to you
|
|
18
|
-
message: |
|
|
19
|
-
Hi {{ contact.name }},
|
|
20
|
-
|
|
21
|
-
**{{ task.title }}** has been assigned to you.
|
|
22
|
-
metadata:
|
|
23
|
-
- label: Due
|
|
24
|
-
value: '{{ task.due_date }}'
|
|
25
|
-
button:
|
|
26
|
-
label: View task
|
|
27
|
-
testData:
|
|
28
|
-
contact:
|
|
29
|
-
name: Jane Doe
|
|
30
|
-
task:
|
|
31
|
-
title: Review the quarterly report
|
|
32
|
-
due_date: 2026-07-15
|
|
33
|
-
links:
|
|
34
|
-
button:
|
|
35
|
-
pageId: task-view
|
|
36
|
-
urlQuery:
|
|
37
|
-
_id: T-001
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
The definition fields are:
|
|
41
|
-
|
|
42
|
-
- `id: string`: **Required** - A unique notification id, referenced by the `RenderNotification` step.
|
|
43
|
-
- `type: string`: **Required** - The template type — a built-in template (`NotificationEmail`, `DigestEmail`, `AlertEmail`) or a custom template plugin.
|
|
44
|
-
- `properties: object`: **Required** - The template's content. `properties.subject` is always required; the rest depend on the template type.
|
|
45
|
-
- `theme: object`: Per-notification overrides of the `app.email` theme (see [Theming](#theming)).
|
|
46
|
-
- `testData: object`: Sample data used to render the notification in the [email preview](#previewing-emails). Not used at runtime.
|
|
47
|
-
|
|
48
|
-
### Module notifications
|
|
49
|
-
|
|
50
|
-
Modules can ship notification templates: `module.lowdefy.yaml` accepts a `notifications:` section, and each template's id scopes to `{entry}/{id}` (installing `user-admin` gives `user-admin/invite-user`), so the same module installed twice never collides. Module content references its own templates with [`_module.notificationId`](/_module) — in a `RenderNotification` step or a dispatch payload — and app-level config reaches a module's template with the object form (`_module.notificationId: { id: invite-user, module: user-admin }`) or the literal scoped string. This lets a module that drives a notification flow (like user invites) ship its default email instead of every app hand-writing it. Module notifications resolve `_module.var` in their properties, so template copy can be configured through the module's vars.
|
|
51
|
-
|
|
52
|
-
### Interpolation
|
|
53
|
-
|
|
54
|
-
Template property strings interpolate against the render data with [Nunjucks](https://mozilla.github.io/nunjucks/) — `{{ task.title }}` just works, including `{% if %}` conditionals. This applies inside `notifications:` properties only.
|
|
55
|
-
|
|
56
|
-
Interpolated values are **inert** — they can never carry markup or links. A task title of `[click here](https://evil.example)` renders as literal text, not a link. Only the markdown you write in the template formats; the data you interpolate is escaped. This closes the injection risk of putting user data into a branded email.
|
|
57
|
-
|
|
58
|
-
There is no operator evaluation inside template properties — they are data templates, not operator config. Build-time operators like [`_ref`](/references-and-templates) still work as everywhere else.
|
|
59
|
-
|
|
60
|
-
### Links
|
|
61
|
-
|
|
62
|
-
Links live under `data.links` (and inside the arrays a template declares, like `data.actions`), supplied as Lowdefy-native `{ pageId, urlQuery }` objects. The `RenderNotification` step resolves them to full URLs at render time — see [Rendering notifications as a routine step](/lowdefy-api#rendering-notifications-as-a-routine-step). A link that is already an absolute URL string passes through unchanged.
|
|
63
|
-
|
|
64
|
-
## Built-in templates
|
|
65
|
-
|
|
66
|
-
Three templates cover most needs. Each renders only the sections you provide — omit `quote` and no quote block appears.
|
|
67
|
-
|
|
68
|
-
### NotificationEmail
|
|
69
|
-
|
|
70
|
-
The general-purpose template.
|
|
71
|
-
|
|
72
|
-
- `subject: string`: **Required** - Email subject line.
|
|
73
|
-
- `title: string`: Heading shown at the top of the email.
|
|
74
|
-
- `message: string`: Main message, rendered as markdown.
|
|
75
|
-
- `preview: string`: Preview text shown in email client inbox listings.
|
|
76
|
-
- `metadata: object[]`: Label-value pairs rendered as a table. Each item is `{ label, value }`.
|
|
77
|
-
- `quote: object`: A quoted block, `{ text, author }`.
|
|
78
|
-
- `button: object`: A call-to-action button, `{ label }`. Its link is resolved from `data.links.button`.
|
|
79
|
-
|
|
80
|
-
Renders one data key: `data.actions` — an array of `{ title, message, link }` action items, shown as an action list.
|
|
81
|
-
|
|
82
|
-
### DigestEmail
|
|
83
|
-
|
|
84
|
-
For roundups of many items.
|
|
85
|
-
|
|
86
|
-
- `subject: string`: **Required** - Email subject line.
|
|
87
|
-
- `title: string`: Heading shown at the top of the email.
|
|
88
|
-
- `intro: string`: Introductory text, rendered as markdown.
|
|
89
|
-
- `button: object`: A call-to-action button, `{ label }`, linked from `data.links.button`.
|
|
90
|
-
|
|
91
|
-
Renders one data key: `data.items` — an array of `{ title, message, link, meta }` rows.
|
|
92
|
-
|
|
93
|
-
### AlertEmail
|
|
94
|
-
|
|
95
|
-
For status-toned notices.
|
|
96
|
-
|
|
97
|
-
- `subject: string`: **Required** - Email subject line.
|
|
98
|
-
- `tone: string`: One of `info`, `success`, `warning`, or `error`. Sets the accent color.
|
|
99
|
-
- `title: string`: Heading shown at the top of the email.
|
|
100
|
-
- `message: string`: Main message, rendered as markdown.
|
|
101
|
-
- `metadata: object[]`: Label-value pairs rendered as a table.
|
|
102
|
-
- `button: object`: A call-to-action button, `{ label }`, linked from `data.links.button`.
|
|
103
|
-
|
|
104
|
-
### Structured data (`actions`, `items`)
|
|
105
|
-
|
|
106
|
-
Structured arrays are never wired in config — a template documents the data keys it renders, and your pipeline supplies the array under that key (`data.actions` for `NotificationEmail`, `data.items` for `DigestEmail`). Each item's `link` field is resolved to a URL the same way `links.button` is.
|
|
107
|
-
|
|
108
|
-
## Theming
|
|
109
|
-
|
|
110
|
-
One theme per app, under `app.email`:
|
|
111
|
-
|
|
112
|
-
```yaml
|
|
113
|
-
app:
|
|
114
|
-
email:
|
|
115
|
-
logo: https://cdn.myapp.com/logo.png
|
|
116
|
-
companyName: MyApp
|
|
117
|
-
primaryColor: '#1990ff'
|
|
118
|
-
signature: |
|
|
119
|
-
Regards,
|
|
120
|
-
The MyApp Team
|
|
121
|
-
footer: You receive these emails because you have a MyApp account.
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
The layout — logo header, greeting, content, signature, footer — is fixed; the theme parameterizes it. A notification can override any theme field (for example a sub-brand logo) with a `theme:` object; overrides shallow-merge over `app.email`.
|
|
125
|
-
|
|
126
|
-
Two fields default from your existing app config when you don't set them: `companyName` from the app's root `name:`, and `primaryColor` from `theme.antd.token.colorPrimary` — so a branded app gets branded emails without repeating itself. Set a field explicitly (an empty string works as an opt-out for `companyName`) to override the derived value.
|
|
127
|
-
|
|
128
|
-
The `logo` can be an app-relative path to a `public/` asset:
|
|
129
|
-
|
|
130
|
-
```yaml
|
|
131
|
-
app:
|
|
132
|
-
email:
|
|
133
|
-
logo: /logo-light-theme.png
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
A relative logo resolves against the `serverUrl` passed to the `RenderNotification` step (by default the current environment's `url` in `config.environments`), so one config works across environments. Email clients can only load absolute URLs — when no `serverUrl` is available the logo is omitted and the header falls back to the `companyName` text.
|
|
137
|
-
|
|
138
|
-
## Custom templates
|
|
139
|
-
|
|
140
|
-
Rich emails beyond the built-in templates are plugins — plain [React Email](https://react.email/) components. A custom template exports a component receiving `{ properties, data, theme, links }` and a properties schema, and declares its type under a new `notifications` type category — the same registration pattern as other [plugins](/plugins-introduction). Once installed, use it as a `type` in the `notifications:` section like any built-in template.
|
|
141
|
-
|
|
142
|
-
## Sending notifications
|
|
143
|
-
|
|
144
|
-
The framework renders; the pipeline is yours to compose. In an API routine you:
|
|
145
|
-
|
|
146
|
-
1. Render the notification with a [`RenderNotification` step](/lowdefy-api#rendering-notifications-as-a-routine-step), which returns `{ subject, title, preview, html, text, data }`.
|
|
147
|
-
2. Store a record with an ordinary request (for example `MongoDBInsertOne`) if you want an inbox, deduplication, or retries.
|
|
148
|
-
3. Send the email with an email request — [`SMTPMailSend`](/SMTP) or [`SendGridMailSend`](/SendGridMail).
|
|
149
|
-
4. Update the record with the send result.
|
|
150
|
-
|
|
151
|
-
That pipeline is about sixty lines of routine YAML, and you own every choice in it — record shape, deduplication strategy, retry policy. If you'd rather not write it, the official [`modules-mongodb` notifications module](https://github.com/lowdefy/modules-mongodb) ships the whole pipeline (dispatch, dedup, send, tracking) plus an inbox, bell, and mark-as-read landing page — you just define the templates and shape your events into notification items.
|
|
152
|
-
|
|
153
|
-
## Previewing emails
|
|
154
|
-
|
|
155
|
-
The [`lowdefy emails`](/cli#emails) CLI command renders every notification from its `testData` and opens [React Email](https://react.email/)'s preview server, so you can iterate on templates without sending real mail. It warns when a template renders a data key that your `testData` is missing. The preview has no server URL, so a relative `logo` falls back to the `companyName` text header there.
|
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
# Page and App State
|
|
2
|
-
|
|
3
|
-
A Lowdefy app has a few different data objects which can be accessed and modified. The app wide objects are the `global`, `media` and `user` objects. Then there are page specific objects like the `state`, `urlQuery` and `input` objects.
|
|
4
|
-
|
|
5
|
-
## State
|
|
6
|
-
|
|
7
|
-
Each page in a Lowdefy app has a `state` object which serves as the general data store for that page.
|
|
8
|
-
|
|
9
|
-
Every [`input` category block](/blocks) inside the page will have a value in the `state` object, with their `id` as the key in the `state` object. If the block is not visible the input value is removed from the state object.
|
|
10
|
-
|
|
11
|
-
The [`_state`](/_state) operator can be used to read from `state` and the [`SetState`](/SetState) action can be used to modify or add new values in `state` object in the same page from which `SetState` is called.
|
|
12
|
-
|
|
13
|
-
> See [`operators`](/operators) and [`events-and-actions`](/events-and-actions) for more details.
|
|
14
|
-
|
|
15
|
-
Page states remain even as users navigate to new pages - so if a user returns to a page, the state as they left it will remain.
|
|
16
|
-
|
|
17
|
-
### Reading from state
|
|
18
|
-
Here is an example showing how to read `input` block values from `state`:
|
|
19
|
-
```yaml
|
|
20
|
-
id: my-page
|
|
21
|
-
type: PageHeaderMenu
|
|
22
|
-
blocks:
|
|
23
|
-
- id: Name
|
|
24
|
-
type: TextInput
|
|
25
|
-
- id: Age
|
|
26
|
-
type: NumberInput
|
|
27
|
-
- id: MyDisplay
|
|
28
|
-
type: Html
|
|
29
|
-
properties:
|
|
30
|
-
html:
|
|
31
|
-
_string.concat:
|
|
32
|
-
- <b>Name:</b>
|
|
33
|
-
- _state: Name
|
|
34
|
-
- <br/><b>Age:</b>
|
|
35
|
-
- _state: Age
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
### Modifying state
|
|
39
|
-
The following examples demonstrates how to modify `state`:
|
|
40
|
-
```yaml
|
|
41
|
-
id: my-page
|
|
42
|
-
type: PageHeaderMenu
|
|
43
|
-
blocks:
|
|
44
|
-
- id: Name
|
|
45
|
-
type: TextInput
|
|
46
|
-
- id: Age
|
|
47
|
-
type: NumberInput
|
|
48
|
-
- id: Button
|
|
49
|
-
type: Button
|
|
50
|
-
events:
|
|
51
|
-
onClick:
|
|
52
|
-
- id: set_person_object
|
|
53
|
-
type: SetState
|
|
54
|
-
params:
|
|
55
|
-
person:
|
|
56
|
-
name:
|
|
57
|
-
_state: Name
|
|
58
|
-
age:
|
|
59
|
-
_state: Age
|
|
60
|
-
example: true
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
This will result in a `state` which looks like:
|
|
64
|
-
```json5
|
|
65
|
-
{
|
|
66
|
-
"Name": "Alice", // The TextInput value
|
|
67
|
-
"Age": 99, //The NumberInput value
|
|
68
|
-
"person": {
|
|
69
|
-
"name": "Alice",
|
|
70
|
-
"age": 99,
|
|
71
|
-
"example": true
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
## Global
|
|
77
|
-
The `global` object is a single app level data object defined in the Lowdefy [config root](/lowdefy-schema). This object is the same for every page. The `global` object can be modified using the [`SetGlobal`](/SetGlobal) action.
|
|
78
|
-
|
|
79
|
-
> Note that when `SetGlobal` is called, `global` will not be consistent between clients, like different users, or a single user with multiple tabs open.
|
|
80
|
-
|
|
81
|
-
### Reading from global
|
|
82
|
-
This example shows how you can create and read from `global`:
|
|
83
|
-
|
|
84
|
-
`lowdefy.yaml`
|
|
85
|
-
```yaml
|
|
86
|
-
lowdefy: 6.0.0
|
|
87
|
-
global:
|
|
88
|
-
key: value
|
|
89
|
-
pages:
|
|
90
|
-
- id: my-page
|
|
91
|
-
type: PageSiderMenu
|
|
92
|
-
blocks:
|
|
93
|
-
id: DisplayGlobalKey
|
|
94
|
-
type: Html
|
|
95
|
-
html:
|
|
96
|
-
_global: key ## Returns 'value'
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
### Modifying global
|
|
100
|
-
The following examples shows how to modify the `global` object:
|
|
101
|
-
|
|
102
|
-
`lowdefy.yaml`
|
|
103
|
-
```yaml
|
|
104
|
-
lowdefy: 6.0.0
|
|
105
|
-
global:
|
|
106
|
-
key: value
|
|
107
|
-
pages:
|
|
108
|
-
- id: my-page
|
|
109
|
-
type: PageSiderMenu
|
|
110
|
-
blocks:
|
|
111
|
-
- id: DisplayGlobalKey
|
|
112
|
-
type: Html
|
|
113
|
-
html:
|
|
114
|
-
_global: key ## Returns `value`
|
|
115
|
-
- id: ModifyGlobal
|
|
116
|
-
type: Button
|
|
117
|
-
events:
|
|
118
|
-
onClick:
|
|
119
|
-
- id: modify_global_key
|
|
120
|
-
type: SetGlobal
|
|
121
|
-
params:
|
|
122
|
-
key: New Value
|
|
123
|
-
- id: DisplayModifiedGlobalKey
|
|
124
|
-
type: Html
|
|
125
|
-
html:
|
|
126
|
-
_global: key ## Returns `New Value`
|
|
127
|
-
```
|
|
128
|
-
## URL query
|
|
129
|
-
The `urlQuery` object is used to access variables set in the URL. URL query parameters can be set using the `urlQuery` field in the [`Link`](/Link) action and read using the [`_url_query`](/_url_query) operator. It can be useful to create sharable links containing some additional information other than the page route. For example setting a document id in the url so that the document can be retrieved when the link is opened during the page [`onMount`](/events-and-actions) event.
|
|
130
|
-
|
|
131
|
-
> Note that any variables set to `urlQuery` will be visible to users of the app.
|
|
132
|
-
|
|
133
|
-
### Example using `urlQuery` and `Link`
|
|
134
|
-
|
|
135
|
-
`first-page.yaml`
|
|
136
|
-
```yaml
|
|
137
|
-
id: first-page
|
|
138
|
-
type: PageSiderMenu
|
|
139
|
-
blocks:
|
|
140
|
-
- id: LinkButton
|
|
141
|
-
type: Button
|
|
142
|
-
events:
|
|
143
|
-
- id: link_to_second_page
|
|
144
|
-
type: Link
|
|
145
|
-
params:
|
|
146
|
-
pageId: second-page
|
|
147
|
-
urlQuery:
|
|
148
|
-
document-id: ABC123
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
`second-page.yaml`
|
|
152
|
-
```yaml
|
|
153
|
-
id: second-page
|
|
154
|
-
type: PageSiderMenu
|
|
155
|
-
events:
|
|
156
|
-
onMount:
|
|
157
|
-
- id: set_url_id
|
|
158
|
-
type: SetState
|
|
159
|
-
params:
|
|
160
|
-
myDocId:
|
|
161
|
-
_url_query: document-id ## Returns 'ABC123'
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
## Input
|
|
165
|
-
|
|
166
|
-
The `input` object is unique to a page, and works similar to the `urlQuery` object. The `input` object is used to pass information between page transitions. Variables set to the `input` object are not written to the URL, so they are not visible to app users but also cannot be used to share the data in a link since a `input` object is only consistent between one page and the next to which it links. A `input` object is set using the `input` param of the [`Link`](/Link) action or the `input` property of an [`Anchor`](/Anchor) block when linking from a page to another page in the app and can be read using the [`_input`](/_input) operator.
|
|
167
|
-
|
|
168
|
-
> Note `input` cannot be passed between pages when using the `newTab: true` param in the [`Link`](/Link) action.
|
|
169
|
-
|
|
170
|
-
### Example of setting and reading `input`
|
|
171
|
-
|
|
172
|
-
`first-page.yaml`
|
|
173
|
-
```yaml
|
|
174
|
-
id: first-page
|
|
175
|
-
type: PageSiderMenu
|
|
176
|
-
blocks:
|
|
177
|
-
- id: LinkButton
|
|
178
|
-
type: Button
|
|
179
|
-
events:
|
|
180
|
-
- id: link_to_second_page
|
|
181
|
-
type: Link
|
|
182
|
-
params:
|
|
183
|
-
pageId: second-page
|
|
184
|
-
input:
|
|
185
|
-
document-id: 1234
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
`second-page.yaml`
|
|
189
|
-
```yaml
|
|
190
|
-
id: second-page
|
|
191
|
-
type: PageSiderMenu
|
|
192
|
-
events:
|
|
193
|
-
onMount:
|
|
194
|
-
- id: set_input_id
|
|
195
|
-
type: SetState
|
|
196
|
-
params:
|
|
197
|
-
myDocId:
|
|
198
|
-
_input: document-id ## Returns '1234'
|
|
199
|
-
```
|
|
200
|
-
## Media
|
|
201
|
-
|
|
202
|
-
The `media` object contains some information about the client screen size, and can be accessed using the [`_media`](/_media) operator. This can be used to add additional responsive logic to a page.
|
|
203
|
-
|
|
204
|
-
Here is an example showing how to read the screen size of a smartphone:
|
|
205
|
-
```yaml
|
|
206
|
-
id: DisplayScreenSize
|
|
207
|
-
type: Html
|
|
208
|
-
properties:
|
|
209
|
-
html:
|
|
210
|
-
_media: size ## Returns xs if used on phone width screen width < 640px
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
## User
|
|
214
|
-
|
|
215
|
-
If authentication is configured and a user is logged in, data about the user can be accessed using the [`_user`](/_user) operator. See [User Authentication](/users-introduction) for more details.
|
|
216
|
-
|
|
217
|
-
This example shows how to read a logged-in user's username and id:
|
|
218
|
-
```yaml
|
|
219
|
-
id: my-page
|
|
220
|
-
type: PageSiderMenu
|
|
221
|
-
blocks:
|
|
222
|
-
- id: DisplayUserName
|
|
223
|
-
type: Html
|
|
224
|
-
properties:
|
|
225
|
-
html:
|
|
226
|
-
_string.concat:
|
|
227
|
-
- <b>Name: </b>
|
|
228
|
-
- _user: name
|
|
229
|
-
- id: DisplayUserId
|
|
230
|
-
type: Html
|
|
231
|
-
properties:
|
|
232
|
-
html:
|
|
233
|
-
_string.concat:
|
|
234
|
-
- <b>ID: </b>
|
|
235
|
-
- _user: id
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
#### TLDR
|
|
239
|
-
- There are app wide and page specific data objects.
|
|
240
|
-
- App wide are `global`, `media` and `user`.
|
|
241
|
-
- Page specific are `state`, `urlQuery` and `input`.
|
|
242
|
-
- All input blocks write their value to `state`, with the their `id` as the key in the `state` object.
|
|
243
|
-
- Input blocks which are not visible are removed from `state`.
|
|
244
|
-
- The `SetState` action can also modify the `state` object.
|