@loadbare/app 0.13.0 → 0.14.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/dist/build/assemble.d.ts.map +1 -1
- package/dist/build/assemble.js +31 -1
- package/dist/build/assemble.js.map +1 -1
- package/dist/core/lb-constants.d.ts +11 -1
- package/dist/core/lb-constants.d.ts.map +1 -1
- package/dist/core/lb-constants.js +34 -0
- package/dist/core/lb-constants.js.map +1 -1
- package/dist/core/lb-types.d.ts +27 -0
- package/dist/core/lb-types.d.ts.map +1 -1
- package/dist/core/lb-types.js.map +1 -1
- package/dist/hub/lb-apply.d.ts +20 -3
- package/dist/hub/lb-apply.d.ts.map +1 -1
- package/dist/hub/lb-apply.js +64 -8
- package/dist/hub/lb-apply.js.map +1 -1
- package/dist/hub/lb-hub.browser.d.ts.map +1 -1
- package/dist/hub/lb-hub.browser.js +341 -21
- package/dist/hub/lb-hub.browser.js.map +1 -1
- package/dist/server/lb-express.d.ts +13 -3
- package/dist/server/lb-express.d.ts.map +1 -1
- package/dist/server/lb-express.js +30 -12
- package/dist/server/lb-express.js.map +1 -1
- package/dist/server/lb-server.d.ts +31 -1
- package/dist/server/lb-server.d.ts.map +1 -1
- package/dist/server/lb-server.js +112 -2
- package/dist/server/lb-server.js.map +1 -1
- package/docs/TECHREF-1.0.md +294 -21
- package/docs/comparison.md +6 -4
- package/docs/possible-ideas.md +146 -26
- package/docs/reference/custom-elements.md +97 -1
- package/docs/reference/data-binding.md +303 -4
- package/docs/reference/page-files.md +76 -3
- package/docs/reference/server.md +20 -0
- package/docs/reference/widgets.md +33 -10
- package/docs/roadmap.md +9 -2
- package/package.json +1 -1
- package/skills/loadbare-app/SKILL.md +50 -7
- package/skills/loadbare-app/references/TECHREF-1.0.md +294 -21
- package/skills/loadbare-app/references/custom-elements.md +97 -1
- package/skills/loadbare-app/references/data-binding.md +303 -4
- package/skills/loadbare-app/references/page-files.md +76 -3
- package/skills/loadbare-app/references/server.md +20 -0
- package/skills/loadbare-app/references/widgets.md +33 -10
|
@@ -137,10 +137,14 @@ name:
|
|
|
137
137
|
| `name` | The request name, from `lb-request` |
|
|
138
138
|
| `query` | The query the request is for |
|
|
139
139
|
| `key` | The key of the row the request is for |
|
|
140
|
+
| `keys` | The keys of the rows selected, in place of `key` |
|
|
141
|
+
| `rows` | A form's nested rows, by query: each `key` and `values` |
|
|
140
142
|
| `values` | The gathered control values, by column |
|
|
141
143
|
|
|
142
144
|
The hub sends `query`, `key` and `values` when it finds them; see
|
|
143
|
-
[Gathering](./data-binding.md#gathering).
|
|
145
|
+
[Gathering](./data-binding.md#gathering). It sends `keys` for a request that
|
|
146
|
+
acts on the rows the user selected; see
|
|
147
|
+
[Selecting rows](./data-binding.md#selecting-rows).
|
|
144
148
|
|
|
145
149
|
### onPageEnter
|
|
146
150
|
|
|
@@ -191,10 +195,34 @@ the query they operate on:
|
|
|
191
195
|
|
|
192
196
|
| Request name | Runs | `run` receives |
|
|
193
197
|
|-----------------|-------------|------------------|
|
|
194
|
-
| `lb-row-insert` | `rowInsert` | `query`, `values` |
|
|
195
|
-
| `lb-row-update` | `rowUpdate` | `query`, `key`, `values` |
|
|
198
|
+
| `lb-row-insert` | `rowInsert` | `query`, `values`, and `rows` from a form |
|
|
199
|
+
| `lb-row-update` | `rowUpdate` | `query`, `key`, `values`, and `rows` from a form |
|
|
196
200
|
| `lb-row-delete` | `rowDelete` | `query`, `key` |
|
|
197
201
|
|
|
202
|
+
An `lb-row-update` or `lb-row-delete` carrying `keys` runs `rowUpdate` or
|
|
203
|
+
`rowDelete` once for each key, with that key, so a handler written for one
|
|
204
|
+
row serves several. The patches the runs return are laid together, and the
|
|
205
|
+
refresh set runs once. A `url()` returned for one of several rows is
|
|
206
|
+
reported and ignored. A declared request receives `keys` as it is.
|
|
207
|
+
|
|
208
|
+
`rows` holds the rows of a query nested in the form the request came from,
|
|
209
|
+
by query name, each with its `key` and the `values` of its own controls; see
|
|
210
|
+
[A form over a set of rows](./data-binding.md#a-form-over-a-set-of-rows).
|
|
211
|
+
The handler writes the master and its details together, deciding what each
|
|
212
|
+
row's values mean, such as an empty amount being no row at all:
|
|
213
|
+
|
|
214
|
+
```ts
|
|
215
|
+
rowInsert: {
|
|
216
|
+
run: async (ctx, { values, rows }) => {
|
|
217
|
+
const id = await ctx.db.insertPaycheck(values);
|
|
218
|
+
for (const { key, values: row } of rows?.deduction_types ?? []) {
|
|
219
|
+
if (row.amount !== "") await ctx.db.insertDeduction(id, key, row.amount);
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
refresh: ["paychecks"],
|
|
223
|
+
},
|
|
224
|
+
```
|
|
225
|
+
|
|
198
226
|
```ts
|
|
199
227
|
// src/pages/directory.requests.ts
|
|
200
228
|
import { patch, type Requests } from "@loadbare/app/server";
|
|
@@ -333,3 +361,48 @@ Post/Redirect/Get without the redirect. The refresh set does not run, and
|
|
|
333
361
|
nothing else `run` returned is sent, since both answered for the URL the page
|
|
334
362
|
left. The loaded page reads the new parms through `contextFor`; see
|
|
335
363
|
[the Express server](./server.md#database-layer).
|
|
364
|
+
|
|
365
|
+
### Refusing a request
|
|
366
|
+
|
|
367
|
+
A handler refuses a request by throwing `refusal()`, with words written for
|
|
368
|
+
the user:
|
|
369
|
+
|
|
370
|
+
```ts
|
|
371
|
+
import { refusal, type Requests } from "@loadbare/app/server";
|
|
372
|
+
|
|
373
|
+
export const requests: Requests = {
|
|
374
|
+
handlers: {
|
|
375
|
+
enterPaycheck: {
|
|
376
|
+
run: async (ctx, { values }) => {
|
|
377
|
+
if (Number(values!.amount) <= 0) {
|
|
378
|
+
throw refusal({ amount: "Must be more than zero" });
|
|
379
|
+
}
|
|
380
|
+
const overlap = await ctx.db.overlappingSeries(values!);
|
|
381
|
+
if (overlap) {
|
|
382
|
+
throw refusal(
|
|
383
|
+
`That series already has paychecks from ${overlap.from} through ${overlap.to}.`,
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
await ctx.db.enterPaycheck(values!);
|
|
387
|
+
},
|
|
388
|
+
refresh: ["paychecks"],
|
|
389
|
+
},
|
|
390
|
+
},
|
|
391
|
+
};
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
| Call | The browser shows |
|
|
395
|
+
|----------------------------------|--------------------------------------------|
|
|
396
|
+
| `refusal("message")` | The message, for the request as a whole |
|
|
397
|
+
| `refusal({ column: "message" })` | Each message on the control for its column |
|
|
398
|
+
| `refusal("message", { ... })` | Both |
|
|
399
|
+
|
|
400
|
+
Throw it, from the handler or from anything the handler calls, and whatever
|
|
401
|
+
the application has open rolls back as for any throw. A column names a
|
|
402
|
+
control the request gathered. See [Refusals](./data-binding.md#refusals)
|
|
403
|
+
for how the browser shows them.
|
|
404
|
+
|
|
405
|
+
A refusal is the only error whose words reach the browser. Anything else a
|
|
406
|
+
handler throws is a failure, answered with nothing in it, so a stack or a
|
|
407
|
+
database message never reaches a page.
|
|
408
|
+
|
package/docs/reference/server.md
CHANGED
|
@@ -72,6 +72,26 @@ path, so the application cannot be hosted under a subpath such as
|
|
|
72
72
|
whole path space through unchanged.
|
|
73
73
|
|
|
74
74
|
Leave `express.json()` to `hubRoutes`, which mounts it on its own routes.
|
|
75
|
+
Pass its options through `hubRoutes` instead.
|
|
76
|
+
|
|
77
|
+
## Options
|
|
78
|
+
|
|
79
|
+
`hubRoutes` takes an optional third argument, an object with one key per
|
|
80
|
+
concern:
|
|
81
|
+
|
|
82
|
+
| Option | Description |
|
|
83
|
+
|--------|----------------------------------------------------------|
|
|
84
|
+
| `json` | Options for `express.json()`, passed to it unchanged |
|
|
85
|
+
|
|
86
|
+
A request body over 100 KB, the `express.json()` default, is refused with a
|
|
87
|
+
413 before any handler runs, and the server log names the option that raises
|
|
88
|
+
it. Raise it for an application whose pages send a file's text as a value:
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
app.use(hubRoutes(hub, contextFor, { json: { limit: "5mb" } }));
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The limit covers every page's requests.
|
|
75
95
|
|
|
76
96
|
## Running the server
|
|
77
97
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# The Basic Widget Library
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
`lb-unknown-page`, `lb-confirm`, `lb-form`, `lb-insert-dialog
|
|
5
|
-
`lb-master`. Every one of them is an ordinary custom element, written
|
|
3
|
+
Eleven widgets: `lb-input`, `lb-select`, `lb-options`, `lb-picker`,
|
|
4
|
+
`lb-table`, `lb-unknown-page`, `lb-confirm`, `lb-form`, `lb-insert-dialog`,
|
|
5
|
+
`lb-master` and `lb-checkbox`. Every one of them is an ordinary custom element, written
|
|
6
6
|
against the contracts in [Custom Elements](./custom-elements.md#html) for its
|
|
7
7
|
definition and [Custom Elements](./custom-elements.md#code) for its class.
|
|
8
8
|
|
|
@@ -26,7 +26,9 @@ for where a listed package sits in the cascade.
|
|
|
26
26
|
`lb-input`, `lb-select`, `lb-options` and `lb-picker` are controls:
|
|
27
27
|
form-associated custom elements with a `value` property that fire `change`.
|
|
28
28
|
Each carries `lb-column` and `lb-request` itself, the way an `<input>` does;
|
|
29
|
-
see [Being a control](./custom-elements.md#being-a-control).
|
|
29
|
+
see [Being a control](./custom-elements.md#being-a-control). Each passes a
|
|
30
|
+
refusal's message for its column to the native control inside it; see
|
|
31
|
+
[Refusals](./data-binding.md#refusals).
|
|
30
32
|
|
|
31
33
|
## `lb-input`
|
|
32
34
|
|
|
@@ -186,8 +188,8 @@ succeeded, and leaves it open on a refusal.
|
|
|
186
188
|
## `lb-form`
|
|
187
189
|
|
|
188
190
|
A `<form>` over one row's controls. A row with a key saves each control's
|
|
189
|
-
column on `change`; a row whose key is empty is new, and the
|
|
190
|
-
|
|
191
|
+
column on `change`; a row whose key is empty is new, and the hub sends no
|
|
192
|
+
update for it, so its controls wait for a submit. A definition only.
|
|
191
193
|
|
|
192
194
|
| Parameter | Fills |
|
|
193
195
|
|-----------|-----------------|
|
|
@@ -210,16 +212,37 @@ answers with a patch holding the new row.
|
|
|
210
212
|
|
|
211
213
|
## `lb-master`
|
|
212
214
|
|
|
213
|
-
A set, one of its rows, and the buttons that act on the set:
|
|
214
|
-
Save new and Cancel, each shown only for a row on record or a new
|
|
215
|
-
definition only, built from `lb-form` and `lb-confirm`.
|
|
216
|
-
|
|
215
|
+
A set, one of its rows, and the buttons that act on the set: New, Copy,
|
|
216
|
+
Delete, Save new and Cancel, each shown only for a row on record or a new
|
|
217
|
+
one. A definition only, built from `lb-form` and `lb-confirm`. New sends
|
|
218
|
+
`new` and Copy sends `copy`, requests the page declares; `new` returns
|
|
219
|
+
`url()` emptying the parm that names the row.
|
|
217
220
|
|
|
218
221
|
| Parameter | Fills |
|
|
219
222
|
|---------------|--------------------------------------------|
|
|
220
223
|
| `exp-row` | The `lb-query` of the row the form shows |
|
|
221
224
|
| `exp-form-id` | The form's `id`, `master-form` when absent |
|
|
222
225
|
|
|
226
|
+
## `lb-checkbox`
|
|
227
|
+
|
|
228
|
+
A checkbox and its label as one element, for an application to style. A
|
|
229
|
+
definition only: a native checkbox is already a control (see
|
|
230
|
+
[Checkboxes](./data-binding.md#checkboxes)), so the widget is the markup, a
|
|
231
|
+
`<label>` holding the `<input type="checkbox">` and a `<span>` with the
|
|
232
|
+
text. The column and request go on the checkbox inside, so they arrive as
|
|
233
|
+
expansion attributes.
|
|
234
|
+
|
|
235
|
+
Unlike `lb-input`, it has no script making the tag the control. A value
|
|
236
|
+
that lands before a widget's script has loaded arrives only as the string
|
|
237
|
+
stamp `lb-column-value`, and a script checkbox would read `"false"` as
|
|
238
|
+
checked. The hub sets a native checkbox's `checked` directly.
|
|
239
|
+
|
|
240
|
+
| Parameter | Fills |
|
|
241
|
+
|---------------|-----------------------------------------------|
|
|
242
|
+
| `exp-column` | The checkbox's `lb-column` |
|
|
243
|
+
| `exp-label` | The label's text |
|
|
244
|
+
| `exp-request` | The checkbox's `lb-request`, none when absent |
|
|
245
|
+
|
|
223
246
|
## `lb-unknown-page`
|
|
224
247
|
|
|
225
248
|
The chrome's dialog for a URL that names no page, as one tag:
|
package/docs/roadmap.md
CHANGED
|
@@ -102,6 +102,14 @@ Most valuable against a large imported widget library, where an app uses a
|
|
|
102
102
|
small fraction of what ships. Revisit when a real app's `app.css` is big
|
|
103
103
|
enough to measure.
|
|
104
104
|
|
|
105
|
+
### Options on `createHub`
|
|
106
|
+
|
|
107
|
+
Global hooks, transaction wrapping, error handling and a CSRF token each
|
|
108
|
+
want an option on `createHub`, `hubRoutes`, or both. `hubRoutes` already
|
|
109
|
+
takes a trailing options object, one key per concern. `createHub` takes
|
|
110
|
+
the same shape when its first option arrives, which adds a parameter and
|
|
111
|
+
breaks nothing.
|
|
112
|
+
|
|
105
113
|
### Queries stated by the chrome
|
|
106
114
|
|
|
107
115
|
A custom element in the chrome naming a query forces every page to declare
|
|
@@ -109,8 +117,7 @@ that query, since the page load covers one page's set. `lb-url` shows the
|
|
|
109
117
|
pattern from the framework side, and an application has no equivalent.
|
|
110
118
|
|
|
111
119
|
A chrome-level query set on `createHub` would close this, and it is additive.
|
|
112
|
-
It takes its place in the options
|
|
113
|
-
[TECHREF-1.0](./TECHREF-1.0.md#the-server-api).
|
|
120
|
+
It takes its place in the [options on `createHub`](#options-on-createhub).
|
|
114
121
|
|
|
115
122
|
### Data binding utilities
|
|
116
123
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: loadbare-app
|
|
3
|
-
description: Build server-bound web applications with Loadbare/app. Covers the file conventions the builder finds by name (`chrome.html`, `*.page.html`, `*.queries.ts`, `*.requests.ts`, `imports.ts`, `<tag>.html`, `<tag>.browser.ts`); the `lb-*` attribute vocabulary that lands query rows on HTML and issues requests (`lb-query`, `lb-column`, `lb-show`, `lb-request`); queries declared with `row(key, run)` and `rows(key, run)`; the URL as the hub's own query `lb-url`, with `lb-url-link`, `lb-url-push` and `lb-url-unknown`; build-time expansion with `exp-*` parameters, `lb-exp-slot` and `lb-exp-template`; custom elements as form-associated controls and row hosts; the Express wiring with `hubRoutes`; and the `@loadbare/widgets` library. Use whenever a task involves `@loadbare/app`, `@loadbare/widgets`, `loadbare-app-build`, an `lb-` attribute, or a page, query, request or custom element file in a Loadbare application. The model is not React, htmx or REST, and cannot be inferred from them.
|
|
3
|
+
description: Build server-bound web applications with Loadbare/app. Covers the file conventions the builder finds by name (`chrome.html`, `*.page.html`, `*.queries.ts`, `*.requests.ts`, `imports.ts`, `<tag>.html`, `<tag>.browser.ts`); the `lb-*` attribute vocabulary that lands query rows on HTML and issues requests (`lb-query`, `lb-column`, `lb-show`, `lb-request`); queries declared with `row(key, run)` and `rows(key, run)`; the URL as the hub's own query `lb-url`, with `lb-url-link`, `lb-url-push` and `lb-url-unknown`; one form pointed at a row by the `--lb-edit`, `--lb-new` and `--lb-release` commands; build-time expansion with `exp-*` parameters, `lb-exp-slot` and `lb-exp-template`; custom elements as form-associated controls and row hosts; the Express wiring with `hubRoutes`; and the `@loadbare/widgets` library. Use whenever a task involves `@loadbare/app`, `@loadbare/widgets`, `loadbare-app-build`, an `lb-` attribute, or a page, query, request or custom element file in a Loadbare application. The model is not React, htmx or REST, and cannot be inferred from them.
|
|
4
4
|
license: Apache-2.0
|
|
5
5
|
metadata:
|
|
6
6
|
package: "@loadbare/app"
|
|
@@ -178,7 +178,11 @@ from it.
|
|
|
178
178
|
query under two names. Many masters with their details is one `rows` query
|
|
179
179
|
of joined rows, ordered by the master first and shown in groups. A
|
|
180
180
|
query nested inside another query's row template receives the same rows in
|
|
181
|
-
every outer row; use it for a picker, never for per-row detail.
|
|
181
|
+
every outer row; use it for a picker, never for per-row detail. Inside a
|
|
182
|
+
form, the live rows of a query nested in the form's own are gathered as
|
|
183
|
+
`rows: { <query>: [{ key, values }] }` beside `values`, so a master and a
|
|
184
|
+
subtable of its details (one input per type, say) are entered in one
|
|
185
|
+
submit, and the master's handler writes both. A new outer
|
|
182
186
|
row is filled from the nested query's last answer, whatever order they land
|
|
183
187
|
in.
|
|
184
188
|
|
|
@@ -206,7 +210,8 @@ leaving row or group `lb-row-leaving` or `lb-group-leaving`, removing it once
|
|
|
206
210
|
its animations end. Scrolling to a row is script, in `lbRowsLanded`.
|
|
207
211
|
|
|
208
212
|
**Every request has one shape.** `lb-request` names the request, and the
|
|
209
|
-
hub sends `{ name, query, key, values }` as present
|
|
213
|
+
hub sends `{ name, query, key, values }` as present, with `keys` in place
|
|
214
|
+
of `key` for the rows the user selected: `query` from the
|
|
210
215
|
nearest ancestor `lb-query`, `key` from the nearest ancestor row of that
|
|
211
216
|
query, and `values` gathered from controls by their `lb-column`.
|
|
212
217
|
|
|
@@ -224,9 +229,10 @@ with `lb-column` gathers its own value alone. A `<form>` gathers every
|
|
|
224
229
|
control whose form owner it is. An element in a live row gathers that live
|
|
225
230
|
row. Anything else gathers its form owner's controls. A `<form>` cannot
|
|
226
231
|
wrap a `<tr>`, so an insert row in a table puts its controls in a form
|
|
227
|
-
elsewhere with the HTML `form` attribute.
|
|
228
|
-
|
|
229
|
-
|
|
232
|
+
elsewhere with the HTML `form` attribute. A checkbox is a control: checked
|
|
233
|
+
unless its column is `false` or null, and gathered as `"true"` or `"false"`.
|
|
234
|
+
Radio buttons and file inputs are not controls here: they receive no value
|
|
235
|
+
and are not gathered.
|
|
230
236
|
|
|
231
237
|
**A form that adds to a set chosen elsewhere is written once, outside every
|
|
232
238
|
row.** A form cannot sit inside another form or in a table row, so a dialog
|
|
@@ -234,6 +240,17 @@ that creates an account while a posting's picker is choosing one goes at the
|
|
|
234
240
|
end of the page, and each row opens it with `commandfor`. The dialog learns
|
|
235
241
|
the new key from `lb-request-done`.
|
|
236
242
|
|
|
243
|
+
**A set the user edits has one form, pointed at a row.** Never put a form
|
|
244
|
+
in every row. Write one form naming the set's query, outside every row,
|
|
245
|
+
often in a `<dialog>`, and give it an `id`. A `type="button"` with
|
|
246
|
+
`commandfor="<id>"` and `command="--lb-edit"` in a live row fills it from
|
|
247
|
+
that row with no round trip; `--lb-new` starts it empty for an insert;
|
|
248
|
+
`--lb-release` lets it go. The form's `lb-key-value` is the row's key, empty
|
|
249
|
+
for a new row, absent when not in use, and a stylesheet shows Save or Save
|
|
250
|
+
new by it. A successful request from the form, or its dialog closing, lets
|
|
251
|
+
it go. Which row is being edited is never a query parm. A row that must be
|
|
252
|
+
fetched to be edited is another page, with that row as its master.
|
|
253
|
+
|
|
237
254
|
**Three requests are Loadbare's.** `lb-row-insert` needs `query` and
|
|
238
255
|
`values`, `lb-row-update` needs `query`, `key` and `values`, and
|
|
239
256
|
`lb-row-delete` needs `query` and `key`. The page permits each under
|
|
@@ -242,6 +259,32 @@ Each works on a `row` query as well as a `rows` query, since the element a
|
|
|
242
259
|
`row` lands on carries its key. Every other request name is a declared
|
|
243
260
|
request, under `handlers`. Anything undeclared is refused.
|
|
244
261
|
|
|
262
|
+
**An empty key is a row not yet entered.** A `row` query answering with an
|
|
263
|
+
empty key, or a form `--lb-new` pointed, carries `lb-key-value=""`. The hub
|
|
264
|
+
sends inserts and declared requests from it with no `key`, and sends no
|
|
265
|
+
update or delete at all, silently. So a control with
|
|
266
|
+
`lb-request="lb-row-update"` saves on a row on record and only holds its
|
|
267
|
+
value on a new one. Never write script to stop such an update.
|
|
268
|
+
|
|
269
|
+
**Select rows with `lb-select`, never with a column.** An
|
|
270
|
+
`<input type="checkbox" lb-select>` in a row template selects its row; the
|
|
271
|
+
hub stamps `lb-row-selected`. A request for that query naming no one row,
|
|
272
|
+
such as a form outside the rows, carries the ticked rows as `keys`.
|
|
273
|
+
`rowUpdate` and `rowDelete` then run once per key with no new code; a
|
|
274
|
+
declared request gets `keys` itself. With none ticked an update or delete
|
|
275
|
+
is not sent. Success clears the selection, and so does `lb-show` hiding a
|
|
276
|
+
selector. A selecting mode kept in the URL reaches the rows as a column the
|
|
277
|
+
query computes from the parm.
|
|
278
|
+
|
|
279
|
+
**Refuse with `refusal()`, never with a plain throw.** `throw
|
|
280
|
+
refusal("message")`, `throw refusal({ column: "message" })` or both, from
|
|
281
|
+
`@loadbare/app/server`. The whole-request message lands as the
|
|
282
|
+
`lb-request-refused` stamp on the element that committed, shown by CSS
|
|
283
|
+
`attr()`; each column's message goes on its control by
|
|
284
|
+
`setCustomValidity`, and the first is reported. Editing anything the
|
|
285
|
+
request gathered withdraws it all. Any other throw is a failure with no
|
|
286
|
+
message, so a database error never reaches the page.
|
|
287
|
+
|
|
245
288
|
**Write `rowUpdate` as a partial update.** A form sends every control it
|
|
246
289
|
owns; a single control sends its one column. Set the columns `values`
|
|
247
290
|
names, leave the rest alone, and check the names against the columns the
|
|
@@ -395,7 +438,7 @@ own, or to act on rows once they land through the hook the hub calls,
|
|
|
395
438
|
|
|
396
439
|
Before writing one, check `@loadbare/widgets`: `lb-input`, `lb-select`,
|
|
397
440
|
`lb-options`, `lb-picker`, `lb-table`, `lb-unknown-page`, `lb-confirm`,
|
|
398
|
-
`lb-form`, `lb-insert-dialog`, `lb-master`. The first four are
|
|
441
|
+
`lb-form`, `lb-insert-dialog`, `lb-master`, `lb-checkbox`. The first four are
|
|
399
442
|
form-associated controls that carry `lb-column` and `lb-request`
|
|
400
443
|
themselves. Install the package and list it in `src/imports.ts`:
|
|
401
444
|
|