@loadbare/app 0.25.0 → 0.27.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 +1 -2
- package/dist/build/assemble.d.ts.map +1 -1
- package/dist/build/assemble.js +31 -37
- package/dist/build/assemble.js.map +1 -1
- package/dist/build/cli.d.ts +4 -10
- package/dist/build/cli.d.ts.map +1 -1
- package/dist/build/cli.js +11 -33
- package/dist/build/cli.js.map +1 -1
- package/dist/build/declared.js +1 -1
- package/dist/build/declared.js.map +1 -1
- package/dist/core/lb-constants.d.ts +15 -13
- package/dist/core/lb-constants.d.ts.map +1 -1
- package/dist/core/lb-constants.js +47 -51
- package/dist/core/lb-constants.js.map +1 -1
- package/dist/core/lb-types.d.ts +12 -11
- package/dist/core/lb-types.d.ts.map +1 -1
- package/dist/core/lb-types.js +7 -0
- package/dist/core/lb-types.js.map +1 -1
- package/dist/hub/lb-apply.d.ts +10 -34
- package/dist/hub/lb-apply.d.ts.map +1 -1
- package/dist/hub/lb-apply.js +92 -151
- 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 +115 -127
- package/dist/hub/lb-hub.browser.js.map +1 -1
- package/dist/hub/lb-lifecycle.d.ts.map +1 -1
- package/dist/hub/lb-lifecycle.js +4 -11
- package/dist/hub/lb-lifecycle.js.map +1 -1
- package/dist/server/lb-express.d.ts.map +1 -1
- package/dist/server/lb-express.js +3 -3
- package/dist/server/lb-express.js.map +1 -1
- package/dist/server/lb-server.d.ts +35 -19
- package/dist/server/lb-server.d.ts.map +1 -1
- package/dist/server/lb-server.js +141 -88
- package/dist/server/lb-server.js.map +1 -1
- package/docs/binding-cases.md +150 -0
- package/docs/comparison.md +34 -38
- package/docs/opinions.md +2 -2
- package/docs/reference/chrome.md +8 -10
- package/docs/reference/css.md +9 -10
- package/docs/reference/custom-elements.md +11 -8
- package/docs/reference/data-binding.md +93 -134
- package/docs/reference/names.md +21 -22
- package/docs/reference/page-files.md +24 -26
- package/docs/reference/server.md +3 -4
- package/docs/roadmap.md +2 -2
- package/docs/testing.md +5 -6
- package/package.json +1 -1
- package/skills/loadbare-app/SKILL.md +55 -48
- package/skills/loadbare-app/references/chrome.md +8 -10
- package/skills/loadbare-app/references/css.md +9 -10
- package/skills/loadbare-app/references/custom-elements.md +11 -8
- package/skills/loadbare-app/references/data-binding.md +93 -134
- package/skills/loadbare-app/references/names.md +21 -22
- package/skills/loadbare-app/references/page-files.md +24 -26
- package/skills/loadbare-app/references/server.md +3 -4
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A page shows server data by naming queries and columns in its HTML, and asks
|
|
4
4
|
the server to change that data by naming requests. The developer writes
|
|
5
|
-
|
|
5
|
+
ten `lb-` attributes. The server declares every query a page may show and
|
|
6
6
|
every request it may send, and refuses anything it has not declared.
|
|
7
7
|
|
|
8
8
|
Everything is a query. A query is a name for rows, of kind `row` or `rows`,
|
|
@@ -46,12 +46,9 @@ each with its key, and permits the three requests on `roster`; see
|
|
|
46
46
|
| `lb-query` | Any element | The query whose rows land in it |
|
|
47
47
|
| `lb-column` | Any element | The column it shows, and the column it gathers |
|
|
48
48
|
| `lb-show` | Any element but `<template>` | The column that decides whether it is present |
|
|
49
|
-
| `lb-
|
|
50
|
-
| `lb-filter` | An element with `lb-query` | The columns a choice filters; see [Filters](#filters) |
|
|
49
|
+
| `lb-filter` | An element with `lb-query` | The columns the user may filter; see [Filters](#filters) |
|
|
51
50
|
| `lb-group` | A `<template>` | Nothing: it marks a group template; see [Groups](#groups) |
|
|
52
|
-
| `lb-
|
|
53
|
-
| `lb-sum`, `lb-avg`, `lb-min`, `lb-max` | Any element | The column aggregated; see [Aggregates](#aggregates) |
|
|
54
|
-
| `lb-select` | A checkbox in a row template | Nothing: it selects its live row; see [Selecting rows](#selecting-rows) |
|
|
51
|
+
| `lb-aggregate` | Any element | The function it applies to `lb-column`; see [Aggregates](#aggregates) |
|
|
55
52
|
| `lb-request` | Any element | The request it sends when it commits |
|
|
56
53
|
| `lb-url-link` | An `<a>` | A link between pages; see [chrome](./chrome.md#links) |
|
|
57
54
|
| `lb-url-parm` | An `<a lb-url-link>` in a row | Columns of the row its `href` carries as parms; see [chrome](./chrome.md#a-link-from-a-row) |
|
|
@@ -73,7 +70,6 @@ builder writes a stamp, and a stylesheet or a custom element reads it.
|
|
|
73
70
|
| `lb-row-created`, `lb-row-changed`, `lb-row-moved`, `lb-row-requested`, `lb-row-unplaced` | What happened to a row; see [What happened to a row](#what-happened-to-a-row) |
|
|
74
71
|
| `lb-row-leaving`, `lb-group-leaving` | A row or group on its way out |
|
|
75
72
|
| `lb-row-editing` | The row a form is pointed at; see [Editing a row in one form](#editing-a-row-in-one-form) |
|
|
76
|
-
| `lb-row-selected` | A row whose `lb-select` is ticked |
|
|
77
73
|
| `lb-request-pending` | The element's request is in flight |
|
|
78
74
|
| `lb-request-error` | The element's last request failed |
|
|
79
75
|
| `lb-request-refused` | The handler refused it; see [Refusals](#refusals) |
|
|
@@ -185,7 +181,7 @@ or `""`:
|
|
|
185
181
|
|
|
186
182
|
A checkbox lands what it sends, so it shows the same state after a round
|
|
187
183
|
trip through a query whose values are strings, such as `lb-url` or
|
|
188
|
-
`lb-
|
|
184
|
+
`lb-filters`. A query parm the URL does not carry lands as `""`, so the
|
|
189
185
|
checkbox is unchecked. Unchecked sends `"false"` rather than nothing, so a
|
|
190
186
|
flag can be set back. A checkbox carrying a `value` attribute is not a flag
|
|
191
187
|
but one of a set, holding a query parm the URL repeats; see
|
|
@@ -271,25 +267,22 @@ roster: rows("id", (ctx) => ctx.db.members(), { order: "team,name" }),
|
|
|
271
267
|
With no order, rows show in the order they arrived, and a patch's new rows
|
|
272
268
|
go last.
|
|
273
269
|
|
|
274
|
-
The user's order replaces the server's.
|
|
275
|
-
|
|
276
|
-
column holds an order written the same way
|
|
277
|
-
server's order places the rows:
|
|
270
|
+
The user's order replaces the server's. The hub serves the query
|
|
271
|
+
[`lb-sort`](#sort-and-filters), one row per `rows` query, keyed by the
|
|
272
|
+
query's name, whose `order` column holds an order written the same way.
|
|
273
|
+
While it is empty, the server's order places the rows:
|
|
278
274
|
|
|
279
275
|
```html
|
|
280
|
-
<
|
|
281
|
-
<select lb-column="roster_order" lb-request="lb-row-update">
|
|
282
|
-
<option value="">By team</option>
|
|
283
|
-
<option value="name">By name</option>
|
|
284
|
-
<option value="-joined">Newest first</option>
|
|
285
|
-
</select>
|
|
286
|
-
</div>
|
|
287
|
-
|
|
288
|
-
<ul lb-query="roster" lb-order="roster_order">
|
|
276
|
+
<ul lb-query="roster">
|
|
289
277
|
<template><li lb-column="name"></li></template>
|
|
290
278
|
</ul>
|
|
291
279
|
```
|
|
292
280
|
|
|
281
|
+
A control makes a choice by sending `lb-row-update` for `lb-sort`, keyed by
|
|
282
|
+
the query's name; the `<lb-table>` widget's sortable headings do this for
|
|
283
|
+
each column. The hub places the rows again from the ones it already holds,
|
|
284
|
+
and tells the server through `onChoices`.
|
|
285
|
+
|
|
293
286
|
| Values | Compare |
|
|
294
287
|
|----------------------|----------------------------------------------|
|
|
295
288
|
| Two numbers | Numerically |
|
|
@@ -321,7 +314,7 @@ user works through them. It names `order`, `filter` or both, separated by a
|
|
|
321
314
|
space:
|
|
322
315
|
|
|
323
316
|
```html
|
|
324
|
-
<lb-table lb-query="entries"
|
|
317
|
+
<lb-table lb-query="entries"
|
|
325
318
|
lb-filter="description, is_unmatched" lb-manual="order filter">
|
|
326
319
|
```
|
|
327
320
|
|
|
@@ -382,20 +375,19 @@ the move.
|
|
|
382
375
|
|
|
383
376
|
Write `lb-filter` on the element carrying `lb-query`, naming the columns of
|
|
384
377
|
its rows the user may filter, separated by commas. The column of
|
|
385
|
-
[`lb-
|
|
378
|
+
[`lb-filters`](#sort-and-filters) of the same name holds the filter for
|
|
379
|
+
each:
|
|
386
380
|
|
|
387
381
|
```html
|
|
388
|
-
<div lb-query="lb-choices">
|
|
389
|
-
<input lb-column="name" lb-request="lb-row-update" placeholder="Name" />
|
|
390
|
-
</div>
|
|
391
|
-
|
|
392
382
|
<ul lb-query="roster" lb-filter="name, team">
|
|
393
383
|
<template><li lb-column="name"></li></template>
|
|
394
384
|
</ul>
|
|
395
385
|
```
|
|
396
386
|
|
|
397
|
-
A
|
|
398
|
-
|
|
387
|
+
A filter is made by sending `lb-row-update` for `lb-filters`, keyed by the
|
|
388
|
+
query's name; the `<lb-table>` widget's selection does this.
|
|
389
|
+
|
|
390
|
+
A row that does not pass every filter is `hidden`. Under `lb-manual="filter"`, a row an answer changed stays
|
|
399
391
|
showing until the rows are placed again; see
|
|
400
392
|
[Placing by hand](#placing-by-hand). A group whose rows are all hidden is hidden too
|
|
401
393
|
([miswart](./miswarts.md#rows-hidden-by-a-filter)). An empty
|
|
@@ -494,23 +486,24 @@ group, and are reported once.
|
|
|
494
486
|
|
|
495
487
|
### Aggregates
|
|
496
488
|
|
|
497
|
-
`lb-
|
|
498
|
-
|
|
499
|
-
|
|
489
|
+
`lb-aggregate` sets an element from the rows of the nearest group around
|
|
490
|
+
it, or of the whole list outside any group. It names the function, and
|
|
491
|
+
`lb-column` names the column:
|
|
500
492
|
|
|
501
493
|
```html
|
|
502
|
-
<tr><td><span lb-count></span> people</td><td lb-sum="salary"></td></tr>
|
|
494
|
+
<tr><td><span lb-aggregate="count"></span> people</td><td lb-aggregate="sum" lb-column="salary"></td></tr>
|
|
503
495
|
```
|
|
504
496
|
|
|
505
|
-
|
|
|
497
|
+
| `lb-aggregate` | Sets the element to |
|
|
506
498
|
|----------------|-----------------------------------------------------------|
|
|
507
|
-
| `
|
|
508
|
-
| `
|
|
509
|
-
| `
|
|
510
|
-
| `
|
|
511
|
-
| `
|
|
512
|
-
|
|
513
|
-
An aggregate lands as a column does, with `lb-column-value
|
|
499
|
+
| `count` | The number of rows; with `lb-column`, the values in it that are not null |
|
|
500
|
+
| `sum` | The sum of the column |
|
|
501
|
+
| `avg` | The average of the column |
|
|
502
|
+
| `min` | The least value of the column, by the [order](#order)'s comparison |
|
|
503
|
+
| `max` | The greatest, likewise |
|
|
504
|
+
|
|
505
|
+
An aggregate lands as a column does, with `lb-column-value`; its
|
|
506
|
+
`lb-column` names the column it totals, and no row lands on it. A sum and an
|
|
514
507
|
average are exact decimals, read from JSON numbers and from strings holding
|
|
515
508
|
a plain decimal, as Postgres sends `numeric`. A sum has as many places as
|
|
516
509
|
the most precise value, and an average up to two more. `null` and empty
|
|
@@ -578,8 +571,8 @@ and its `lbRowsLanded` runs as its rows land. See
|
|
|
578
571
|
[Holding rows](./custom-elements.md#holding-rows).
|
|
579
572
|
|
|
580
573
|
A request always goes to the server, and a query re-runs only when a
|
|
581
|
-
response names it. A [
|
|
582
|
-
the hub kept. A patch that
|
|
574
|
+
response names it. A [sort or a filter](#sort-and-filters) is the one thing
|
|
575
|
+
landed from what the hub kept. A patch that
|
|
583
576
|
arrives before all of a query's rows is not kept, since it is not the whole
|
|
584
577
|
of anything.
|
|
585
578
|
|
|
@@ -753,8 +746,7 @@ Every request has one shape:
|
|
|
753
746
|
```
|
|
754
747
|
|
|
755
748
|
The hub takes `query`, `key` and `values` from where the element sits, and
|
|
756
|
-
sends each when it has one.
|
|
757
|
-
in place of `key`; see [Selecting rows](#selecting-rows). The server runs the handler for the name and
|
|
749
|
+
sends each when it has one. The server runs the handler for the name and
|
|
758
750
|
answers with response items, which land like any others.
|
|
759
751
|
|
|
760
752
|
### Committing
|
|
@@ -1009,10 +1001,10 @@ The hub sends one of these only when it has what the table lists, and
|
|
|
1009
1001
|
otherwise reports to the console. An insert or an update that gathers
|
|
1010
1002
|
nothing is not sent.
|
|
1011
1003
|
|
|
1012
|
-
For a query the hub serves, `lb-url` or `lb-
|
|
1013
|
-
`lb-row-update` itself, with no round trip; see
|
|
1014
|
-
[Query parms](./chrome.md#query-parms) and
|
|
1015
|
-
`lb-hub
|
|
1004
|
+
For a query the hub serves, `lb-url`, `lb-sort` or `lb-filters`, the hub
|
|
1005
|
+
answers `lb-row-update` itself, with no round trip; see
|
|
1006
|
+
[Query parms](./chrome.md#query-parms) and
|
|
1007
|
+
[Sort and filters](#sort-and-filters). `lb-hub-status` takes no request.
|
|
1016
1008
|
|
|
1017
1009
|
A key comes from a live row, or from an element a `row` landed on, so all
|
|
1018
1010
|
three work against either kind:
|
|
@@ -1118,6 +1110,27 @@ The rows a form's answer lands are placed by the list's `lb-manual`, as any
|
|
|
1118
1110
|
answer's are, whether the form was pointed by Edit or by New; see
|
|
1119
1111
|
[Placing by hand](#placing-by-hand).
|
|
1120
1112
|
|
|
1113
|
+
A list nested in the form follows the row the form is bound to. When Edit
|
|
1114
|
+
or New binds the form, the hub drops the list's rows not yet entered and
|
|
1115
|
+
asks the server for the list's query again, as the request `lb-read`, with
|
|
1116
|
+
the bound row's key added to the query string as the parm named for the
|
|
1117
|
+
form's key column. `contextFor` receives it among the parms, and the query
|
|
1118
|
+
reads it as it reads any parm, so one query serves a master the URL names
|
|
1119
|
+
and a master Edit binds. New sends the parm empty, and the query answers
|
|
1120
|
+
with no rows:
|
|
1121
|
+
|
|
1122
|
+
```ts
|
|
1123
|
+
function contextFor(req: Request, parms: URLSearchParams): HubContext {
|
|
1124
|
+
return { db: openDb(), paycheck: parms.get("paycheck_id") ?? "" };
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
deductions: rows("id", (ctx) => ctx.db.deductionsFor(ctx.paycheck)),
|
|
1128
|
+
```
|
|
1129
|
+
|
|
1130
|
+
A form with no list inside it sends nothing when it is bound. An answer
|
|
1131
|
+
that returns after the form is bound to another row, or after the page
|
|
1132
|
+
moved on, lands nothing.
|
|
1133
|
+
|
|
1121
1134
|
A successful request from the form lets it go, as Cancel does: the form
|
|
1122
1135
|
empties, its controls return to their defaults, and the stamps go. A failed
|
|
1123
1136
|
one leaves the form as the user had it, to correct.
|
|
@@ -1145,63 +1158,6 @@ outside a live row of the form's query, Edit for a key the hub holds no row
|
|
|
1145
1158
|
for, and any of these three commands aimed at an element that is not a form
|
|
1146
1159
|
carrying `lb-query`.
|
|
1147
1160
|
|
|
1148
|
-
### Selecting rows
|
|
1149
|
-
|
|
1150
|
-
A checkbox carrying `lb-select` in a row template selects the live row it
|
|
1151
|
-
sits in. It is not a column: it carries no `lb-column`, lands nothing and
|
|
1152
|
-
is not gathered. The hub stamps the row `lb-row-selected` while it is
|
|
1153
|
-
ticked.
|
|
1154
|
-
|
|
1155
|
-
A request for the query that names no one row then acts on the rows
|
|
1156
|
-
selected, and carries their keys as `keys`:
|
|
1157
|
-
|
|
1158
|
-
```html
|
|
1159
|
-
<tbody lb-query="transactions">
|
|
1160
|
-
<template>
|
|
1161
|
-
<tr>
|
|
1162
|
-
<td><input type="checkbox" lb-select lb-show="selecting" /></td>
|
|
1163
|
-
<td lb-column="description"></td>
|
|
1164
|
-
<td lb-column="amount"></td>
|
|
1165
|
-
</tr>
|
|
1166
|
-
</template>
|
|
1167
|
-
</tbody>
|
|
1168
|
-
|
|
1169
|
-
<form lb-query="transactions" lb-request="lb-row-update">
|
|
1170
|
-
<lb-picker lb-query="accounts" lb-column="acct" exp-label="Account" exp-column="name"></lb-picker>
|
|
1171
|
-
<button type="submit">Apply</button>
|
|
1172
|
-
<button type="button" lb-request="lb-row-delete">Delete</button>
|
|
1173
|
-
</form>
|
|
1174
|
-
```
|
|
1175
|
-
|
|
1176
|
-
```json
|
|
1177
|
-
{ "name": "lb-row-update", "query": "transactions", "keys": ["4", "9"], "values": { "acct": "12" } }
|
|
1178
|
-
```
|
|
1179
|
-
|
|
1180
|
-
| Request | With rows selected | With none ticked |
|
|
1181
|
-
|------------------|----------------------------------------|----------------------|
|
|
1182
|
-
| `lb-row-update` | Sent with `keys` | Not sent |
|
|
1183
|
-
| `lb-row-delete` | Sent with `keys` | Not sent |
|
|
1184
|
-
| A declared one | Sent with `keys` | Sent with `keys: []` |
|
|
1185
|
-
| `lb-row-insert` | Sent as ever; the selection is not its | Sent as ever |
|
|
1186
|
-
|
|
1187
|
-
An update or delete with nothing ticked has nothing to act on, and nothing
|
|
1188
|
-
is reported. A request from inside a row still names that row alone. The
|
|
1189
|
-
server runs the page's `rowUpdate` or `rowDelete` once for each key, as for
|
|
1190
|
-
each row alone, and refreshes once; see [crud](./page-files.md#crud).
|
|
1191
|
-
|
|
1192
|
-
After the request succeeds, the hub clears the selection. A failed one
|
|
1193
|
-
leaves it, to try again.
|
|
1194
|
-
|
|
1195
|
-
Only a checkbox that is showing counts. Turning a selector off with
|
|
1196
|
-
`lb-show` also clears its tick, so leaving a selecting mode abandons the
|
|
1197
|
-
selection rather than keeping it out of sight. With every selector off, a
|
|
1198
|
-
request for the query is an ordinary one again.
|
|
1199
|
-
|
|
1200
|
-
Which rows are selected, and whether the page is in a selecting mode, is
|
|
1201
|
-
interaction state. A mode the URL keeps, such as `?selecting=1`, reaches
|
|
1202
|
-
the rows as a column the query computes from the parm, which `lb-show`
|
|
1203
|
-
reads.
|
|
1204
|
-
|
|
1205
1161
|
### Declared requests
|
|
1206
1162
|
|
|
1207
1163
|
A request name the page declares under `handlers` runs the application's
|
|
@@ -1331,7 +1287,7 @@ returns its controls to their defaults, and the hub removes
|
|
|
1331
1287
|
`lb-column-value` from each of them. A cancelled reset keeps both.
|
|
1332
1288
|
|
|
1333
1289
|
A page load that fails lands nothing and is reported to the console, and
|
|
1334
|
-
the query `lb-hub` says so; see [The hub's state](./chrome.md#the-hubs-state).
|
|
1290
|
+
the query `lb-hub-status` says so; see [The hub's state](./chrome.md#the-hubs-state).
|
|
1335
1291
|
A load
|
|
1336
1292
|
started by a request for `lb-url` stamps the element that sent it, as any
|
|
1337
1293
|
request stamps its element.
|
|
@@ -1363,28 +1319,28 @@ answers it with no round trip:
|
|
|
1363
1319
|
See [The URL](./chrome.md#the-url) for its columns, links, history, and the
|
|
1364
1320
|
unknown-page dialog.
|
|
1365
1321
|
|
|
1366
|
-
##
|
|
1322
|
+
## Sort and filters
|
|
1367
1323
|
|
|
1368
|
-
The hub serves
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
`lb-row-update`
|
|
1373
|
-
|
|
1374
|
-
|
|
1324
|
+
The hub serves two queries for how rows show: `lb-sort` and `lb-filters`,
|
|
1325
|
+
one row per `rows` query, keyed by the query's name. `lb-sort` holds each
|
|
1326
|
+
query's order as the server resolved it; `lb-filters` holds each query's
|
|
1327
|
+
filter values. An element makes a sort or a filter by dispatching
|
|
1328
|
+
`lb-request` with `lb-row-update` for `lb-sort` or `lb-filters`, keyed by
|
|
1329
|
+
the query's name; the `<lb-table>` widget's sortable headings and its
|
|
1330
|
+
selection do this; see
|
|
1375
1331
|
[Sending a request](./custom-elements.md#sending-a-request).
|
|
1376
1332
|
|
|
1377
|
-
A
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1333
|
+
A sort or a filter shows with no round trip: the hub places and filters the
|
|
1334
|
+
rows it already holds again, as a round trip carrying the choice would
|
|
1335
|
+
have. Then it sends the server the choice, in `lb-row-update` for `lb-sort`
|
|
1336
|
+
or `lb-filters`. No element waits on it, and the page's
|
|
1337
|
+
[`onChoices`](./page-files.md#onchoices) runs, when it has one, with the
|
|
1338
|
+
query and its new `sort` or `filters`.
|
|
1383
1339
|
|
|
1384
1340
|
Choices hold until the page changes, and a change of query parm keeps them.
|
|
1385
|
-
On entering a page,
|
|
1386
|
-
|
|
1387
|
-
parms, and the URL does not carry them.
|
|
1341
|
+
On entering a page, `lb-sort` and `lb-filters` land empty, unless the
|
|
1342
|
+
page's `onPageEnter` restores them with `sort()` and `filters()`. Choices
|
|
1343
|
+
are not query parms, and the URL does not carry them.
|
|
1388
1344
|
|
|
1389
1345
|
## The markup checks
|
|
1390
1346
|
|
|
@@ -1392,16 +1348,18 @@ The developer writes `lb-` attributes in markup, and script never assigns
|
|
|
1392
1348
|
them. The builder checks the markup of the chrome and of every page, after
|
|
1393
1349
|
expansion, and refuses to build:
|
|
1394
1350
|
|
|
1395
|
-
- an `lb-` attribute that is not one of the
|
|
1351
|
+
- an `lb-` attribute that is not one of the ten the developer writes;
|
|
1396
1352
|
`lb-exp-slot` and `lb-exp-template` are consumed by expansion and never
|
|
1397
1353
|
reach the check
|
|
1398
1354
|
- `lb-request` naming an `lb-` request other than the three Loadbare provides
|
|
1399
1355
|
- `lb-query` naming a query the page does not declare; every page and the
|
|
1400
|
-
chrome may name `lb-url` and `lb-
|
|
1356
|
+
chrome may name `lb-url`, `lb-sort`, `lb-filters` and `lb-hub-status`,
|
|
1357
|
+
and the chrome names no other
|
|
1401
1358
|
- `lb-request` naming a request the page does not declare under `handlers`;
|
|
1402
1359
|
the chrome sends none
|
|
1403
1360
|
- one of the three requests for a query whose `crud` entry does not declare
|
|
1404
|
-
it, or any but `lb-row-update` for `lb-url` or `lb-
|
|
1361
|
+
it, or any but `lb-row-update` for `lb-url`, `lb-sort` or `lb-filters`;
|
|
1362
|
+
the query is
|
|
1405
1363
|
a form's own when the form carries `lb-query`, and otherwise the nearest
|
|
1406
1364
|
`lb-query` around the element
|
|
1407
1365
|
- `lb-url-link` on anything but an `<a>`
|
|
@@ -1416,20 +1374,21 @@ expansion, and refuses to build:
|
|
|
1416
1374
|
- `lb-show` on a `<template>`, or on a row template's root
|
|
1417
1375
|
- `lb-show` with no `lb-query` around it
|
|
1418
1376
|
- `lb-show="!"` or `lb-show="!!column"`, which reverse no column
|
|
1419
|
-
- `lb-
|
|
1420
|
-
no column
|
|
1377
|
+
- `lb-filter` on an element not carrying `lb-query`, or naming no column
|
|
1421
1378
|
- `lb-manual` on an element not carrying `lb-query`, or naming anything but
|
|
1422
1379
|
`order`, `filter` or both
|
|
1423
|
-
- `lb-
|
|
1424
|
-
template
|
|
1380
|
+
- `lb-group` on anything but a `<template>`, or on one holding no
|
|
1381
|
+
`<template>` for its contents
|
|
1382
|
+
- `lb-aggregate` on a `<template>`, naming a function other than `count`,
|
|
1383
|
+
`sum`, `avg`, `min` or `max`, or, for any but `count`, beside no
|
|
1384
|
+
`lb-column`
|
|
1385
|
+
- `lb-count`, `lb-sum`, `lb-avg`, `lb-min` or `lb-max`, with what to write
|
|
1386
|
+
instead
|
|
1425
1387
|
- a `command` beginning `--lb-` that is not one of the four commands
|
|
1426
1388
|
- one of the four commands with no `commandfor`
|
|
1427
1389
|
- `--lb-new` aimed at an element the markup holds that is neither a
|
|
1428
1390
|
`<form>` nor a list carrying `lb-query` nested directly in a form's own
|
|
1429
1391
|
query
|
|
1430
|
-
- `lb-group` on anything but a `<template>`, or on one holding no
|
|
1431
|
-
`<template>` for its contents
|
|
1432
|
-
- an aggregate on a `<template>`, or any but `lb-count` naming no column
|
|
1433
1392
|
- a chrome without exactly one `<lb-hub>` and exactly one `<main>`, a
|
|
1434
1393
|
`<main>` outside `<lb-hub>`, or a `<main>` holding anything but whitespace
|
|
1435
1394
|
- a page carrying an `<lb-hub>` or a `<main>`
|
|
@@ -14,10 +14,9 @@ that declares a query, a handler or a `crud` entry whose name begins with
|
|
|
14
14
|
|
|
15
15
|
| Flag | Default | Names | Defined in |
|
|
16
16
|
| ---------- | ------- | ----------------------------------------- | --------------------------------------------------- |
|
|
17
|
-
| `--src` | `src` | The application's own tree, scanned whole | [Running the builder](./builder.md
|
|
18
|
-
| `--out` | `dist` | Where the builder writes | [Running the builder](./builder.md
|
|
19
|
-
| `--
|
|
20
|
-
| `--minify` | off | Minify `client.js` and `app.css` | [Running the builder](./builder.md#running-the-builder) |
|
|
17
|
+
| `--src` | `src` | The application's own tree, scanned whole | [Running the builder](./builder.md) |
|
|
18
|
+
| `--out` | `dist` | Where the builder writes | [Running the builder](./builder.md) |
|
|
19
|
+
| `--minify` | off | Minify `client.js` and `app.css` | [Running the builder](./builder.md) |
|
|
21
20
|
|
|
22
21
|
## Reserved file names
|
|
23
22
|
|
|
@@ -66,7 +65,7 @@ A widget package declares these. An application never does.
|
|
|
66
65
|
|
|
67
66
|
## Attributes
|
|
68
67
|
|
|
69
|
-
The developer writes
|
|
68
|
+
The developer writes ten attributes in pages and the chrome, and the
|
|
70
69
|
builder refuses any other `lb-` attribute there. `lb-exp-slot` and
|
|
71
70
|
`lb-exp-template` are written for expansion, which removes them before the
|
|
72
71
|
check. The hub and the builder write the rest, as stamps, and script never
|
|
@@ -77,12 +76,10 @@ assigns one.
|
|
|
77
76
|
| `lb-query` | Developer | [Landing](./data-binding.md#landing) |
|
|
78
77
|
| `lb-column` | Developer | [Landing](./data-binding.md#landing) |
|
|
79
78
|
| `lb-show` | Developer | [Conditional rendering](./data-binding.md#conditional-rendering) |
|
|
80
|
-
| `lb-order` | Developer | [Order](./data-binding.md#order) |
|
|
81
79
|
| `lb-filter` | Developer | [Filters](./data-binding.md#filters) |
|
|
82
80
|
| `lb-manual` | Developer | [Placing by hand](./data-binding.md#placing-by-hand) |
|
|
83
81
|
| `lb-group` | Developer | [Groups](./data-binding.md#groups) |
|
|
84
|
-
| `lb-
|
|
85
|
-
| `lb-select` | Developer | [Selecting rows](./data-binding.md#selecting-rows) |
|
|
82
|
+
| `lb-aggregate` | Developer | [Aggregates](./data-binding.md#aggregates) |
|
|
86
83
|
| `lb-request` | Developer | [Requests](./data-binding.md#requests) |
|
|
87
84
|
| `lb-url-link` | Developer | [Links](./chrome.md#links) |
|
|
88
85
|
| `lb-url-parm` | Developer | [A link from a row](./chrome.md#a-link-from-a-row) |
|
|
@@ -100,7 +97,6 @@ assigns one.
|
|
|
100
97
|
| `lb-row-created`, `lb-row-changed`, `lb-row-moved`, `lb-row-requested` | Hub | [What happened to a row](./data-binding.md#what-happened-to-a-row) |
|
|
101
98
|
| `lb-row-leaving`, `lb-group-leaving` | Hub | [What happened to a row](./data-binding.md#what-happened-to-a-row) |
|
|
102
99
|
| `lb-row-editing` | Hub | [Editing a row in one form](./data-binding.md#editing-a-row-in-one-form) |
|
|
103
|
-
| `lb-row-selected` | Hub | [Selecting rows](./data-binding.md#selecting-rows) |
|
|
104
100
|
| `lb-request-pending` | Hub | [Request state](./data-binding.md#request-state) |
|
|
105
101
|
| `lb-request-error` | Hub | [Request state](./data-binding.md#request-state) |
|
|
106
102
|
| `lb-request-refused` | Hub | [Refusals](./data-binding.md#refusals) |
|
|
@@ -116,9 +112,10 @@ them, and a page declares none.
|
|
|
116
112
|
|
|
117
113
|
| Query | Kind | Key | Columns | Defined in |
|
|
118
114
|
| ------------ | ----- | --------- | --------------------------------------------------------------- | ------------------------------------- |
|
|
119
|
-
| `lb-url` | `row` | `lb-path` | `lb-path`, `lb-page-label`,
|
|
120
|
-
| `lb-
|
|
121
|
-
| `lb-
|
|
115
|
+
| `lb-url` | `row` | `lb-path` | `lb-path`, `lb-page-label`, every query parm | [The URL](./chrome.md#the-url) |
|
|
116
|
+
| `lb-sort` | `rows` | `query` | `query`, `order` | [Sort and filters](./data-binding.md#sort-and-filters) |
|
|
117
|
+
| `lb-filters` | `rows` | `query` | `query`, every filter column | [Sort and filters](./data-binding.md#sort-and-filters) |
|
|
118
|
+
| `lb-hub-status` | `row` | `lb-path` | `lb-path`, `lb-load-state`, `lb-server-state`, `lb-error`, `lb-pending`, `lb-as-of` | [The hub's state](./chrome.md#the-hubs-state) |
|
|
122
119
|
|
|
123
120
|
No query parm is reserved: a column of `lb-url` whose name begins with
|
|
124
121
|
`lb-` is never a query parm.
|
|
@@ -176,7 +173,7 @@ accessor or field named `lb` and a capital.
|
|
|
176
173
|
|
|
177
174
|
| Entry point | Exports | Defined in |
|
|
178
175
|
| -------------------------- | ---------------------------------------------------------------- | ---------------------------------------------- |
|
|
179
|
-
| `@loadbare/app/server` | `row`, `rows`, `patch`, `url`, `
|
|
176
|
+
| `@loadbare/app/server` | `row`, `rows`, `patch`, `url`, `sort`, `filters`, `refusal`, `createHub`, and the types `Queries`, `Requests`, `HubContext`, `Hub` | [Page Files](./page-files.md), [The data channel](./server.md#the-data-channel) |
|
|
180
177
|
| `@loadbare/app/express` | `hubRoutes` | [The Express Server](./server.md) |
|
|
181
178
|
| `@loadbare/app/dev` | `devServer`, `appServer`, `gate`, `devProxy`, `DOWN_MESSAGE` | [The Dev Server](./dev-server.md) |
|
|
182
179
|
| `@loadbare/app/build` | `buildApp`, `watchApp` | [Assembling your own](./dev-server.md#assembling-your-own) |
|
|
@@ -207,12 +204,16 @@ imports them rather than writing a string.
|
|
|
207
204
|
| `ATTR_GROUP_COLUMN` | `lb-group-column` |
|
|
208
205
|
| `ATTR_GROUP_VALUE` | `lb-group-value` |
|
|
209
206
|
| `LIVE_GROUP` | `[lb-group-live]`, the selector for a group's element |
|
|
210
|
-
| `
|
|
211
|
-
| `
|
|
207
|
+
| `ATTR_AGGREGATE` | `lb-aggregate` |
|
|
208
|
+
| `AGGREGATE_COUNT`, `AGGREGATE_SUM`, `AGGREGATE_AVG`, `AGGREGATE_MIN`, `AGGREGATE_MAX` | `count`, `sum`, `avg`, `min`, `max` |
|
|
209
|
+
| `AGGREGATES` | All five aggregate functions |
|
|
212
210
|
| `ORDER_DESCENDING` | `-`, written before a column in an order |
|
|
213
211
|
| `COLUMN_TYPES` | `number`, `boolean`, `text` |
|
|
214
|
-
| `
|
|
215
|
-
| `
|
|
212
|
+
| `SORT_QUERY` | `lb-sort` |
|
|
213
|
+
| `SORT_COLUMN_QUERY` | `query` |
|
|
214
|
+
| `SORT_COLUMN_ORDER` | `order` |
|
|
215
|
+
| `FILTERS_QUERY` | `lb-filters` |
|
|
216
|
+
| `FILTERS_COLUMN_QUERY` | `query` |
|
|
216
217
|
| `ATTR_FILTER` | `lb-filter` |
|
|
217
218
|
| `ATTR_MANUAL` | `lb-manual` |
|
|
218
219
|
| `MANUAL_ORDER`, `MANUAL_FILTER` | `order`, `filter`: the sides `lb-manual` names |
|
|
@@ -236,13 +237,12 @@ imports them rather than writing a string.
|
|
|
236
237
|
| `LB_COMMANDS` | All four commands |
|
|
237
238
|
| `LB_COMMAND_PREFIX` | `--lb-` |
|
|
238
239
|
| `ATTR_ROW_EDITING` | `lb-row-editing` |
|
|
239
|
-
| `ATTR_SELECT` | `lb-select` |
|
|
240
|
-
| `ATTR_ROW_SELECTED` | `lb-row-selected` |
|
|
241
240
|
| `LB_RESERVED_PREFIX` | `lb-` |
|
|
242
241
|
| `REQUEST_ROW_INSERT` | `lb-row-insert` |
|
|
243
242
|
| `REQUEST_ROW_UPDATE` | `lb-row-update` |
|
|
244
243
|
| `REQUEST_ROW_DELETE` | `lb-row-delete` |
|
|
245
244
|
| `LB_ROW_REQUESTS` | All three request names |
|
|
245
|
+
| `REQUEST_READ` | `lb-read`, the hub's own read of a bound form's lists; markup never writes it |
|
|
246
246
|
| `LB_METHODS` | The four reserved methods |
|
|
247
247
|
| `BROWSER_LIFECYCLE` | The browser callbacks the build refuses |
|
|
248
248
|
| `KIND_ROW` | `row` |
|
|
@@ -250,8 +250,7 @@ imports them rather than writing a string.
|
|
|
250
250
|
| `URL_QUERY` | `lb-url` |
|
|
251
251
|
| `URL_COLUMN_PATH` | `lb-path` |
|
|
252
252
|
| `URL_COLUMN_PAGE_LABEL` | `lb-page-label` |
|
|
253
|
-
| `
|
|
254
|
-
| `HUB_QUERY` | `lb-hub` |
|
|
253
|
+
| `HUB_QUERY` | `lb-hub-status` |
|
|
255
254
|
| `HUB_COLUMN_LOAD_STATE` | `lb-load-state` |
|
|
256
255
|
| `HUB_COLUMN_SERVER_STATE` | `lb-server-state` |
|
|
257
256
|
| `HUB_COLUMN_ERROR` | `lb-error` |
|
|
@@ -268,7 +267,7 @@ imports them rather than writing a string.
|
|
|
268
267
|
| `ATTR_EXP_TEMPLATE` | `lb-exp-template` |
|
|
269
268
|
| `ATTR_PAGE` | `lb-page` |
|
|
270
269
|
| `ATTR_PAGE_TITLE` | `lb-page-title` |
|
|
271
|
-
| `DEVELOPER_ATTRIBUTES` | The
|
|
270
|
+
| `DEVELOPER_ATTRIBUTES` | The ten attributes a developer writes |
|
|
272
271
|
| `HUB_TAG_NAME` | `lb-hub` |
|
|
273
272
|
| `LB_ENDPOINT` | `/lb` |
|
|
274
273
|
| `LB_REQUEST_TIMEOUT_MS` | `10000` |
|
|
@@ -152,8 +152,8 @@ optional:
|
|
|
152
152
|
|
|
153
153
|
| Key | Runs |
|
|
154
154
|
|---------------|--------------------------------------------------------|
|
|
155
|
-
| `onPageEnter` | Before the page's queries, when the page loads; may move the URL or restore
|
|
156
|
-
| `onChoices` | Each time the user
|
|
155
|
+
| `onPageEnter` | Before the page's queries, when the page loads; may move the URL or restore the user's order and filters |
|
|
156
|
+
| `onChoices` | Each time the user changes the order or a filter |
|
|
157
157
|
| `handlers` | The page's declared requests, by request name |
|
|
158
158
|
| `crud` | The requests Loadbare provides, by query name |
|
|
159
159
|
|
|
@@ -165,14 +165,11 @@ name:
|
|
|
165
165
|
| `name` | The request name, from `lb-request` |
|
|
166
166
|
| `query` | The query the request is for |
|
|
167
167
|
| `key` | The key of the row the request is for |
|
|
168
|
-
| `keys` | The keys of the rows selected, in place of `key` |
|
|
169
168
|
| `rows` | A form's nested rows, by query: each `key` and `values` |
|
|
170
169
|
| `values` | The gathered control values, by column |
|
|
171
170
|
|
|
172
171
|
The hub sends `query`, `key` and `values` when it finds them; see
|
|
173
|
-
[Gathering](./data-binding.md#gathering).
|
|
174
|
-
acts on the rows the user selected; see
|
|
175
|
-
[Selecting rows](./data-binding.md#selecting-rows).
|
|
172
|
+
[Gathering](./data-binding.md#gathering).
|
|
176
173
|
|
|
177
174
|
### onPageEnter
|
|
178
175
|
|
|
@@ -193,34 +190,41 @@ loads there in the same round trip, and that load does not follow
|
|
|
193
190
|
`onPageEnter` again. A `url()` leading to the parms already in hand is
|
|
194
191
|
ignored. See [Moving the URL](#moving-the-url).
|
|
195
192
|
|
|
196
|
-
It may return `
|
|
197
|
-
[
|
|
193
|
+
It may return `sort()` and `filters()`, alone or beside `url()`, to restore
|
|
194
|
+
the user's [order and filters](./data-binding.md#sort-and-filters) for the
|
|
195
|
+
page:
|
|
198
196
|
|
|
199
197
|
```ts
|
|
200
198
|
// src/pages/directory.requests.ts
|
|
201
|
-
import {
|
|
199
|
+
import { sort, filters, url, type Requests } from "@loadbare/app/server";
|
|
202
200
|
|
|
203
201
|
export const requests: Requests = {
|
|
204
202
|
onPageEnter: async (ctx) => {
|
|
205
203
|
const saved = await ctx.db.savedView("directory");
|
|
206
|
-
if (saved)
|
|
204
|
+
if (saved) {
|
|
205
|
+
return {
|
|
206
|
+
...url(saved.parms),
|
|
207
|
+
...sort(saved.order),
|
|
208
|
+
...filters(saved.filters),
|
|
209
|
+
};
|
|
210
|
+
}
|
|
207
211
|
},
|
|
208
|
-
onChoices: (ctx,
|
|
212
|
+
onChoices: (ctx, change) => ctx.db.saveChoices(change),
|
|
209
213
|
};
|
|
210
214
|
```
|
|
211
215
|
|
|
212
|
-
The page load answers `lb-
|
|
213
|
-
When `url()` moves the page, the choices arrive
|
|
214
|
-
URL. `
|
|
215
|
-
least one of them; anything else is
|
|
216
|
-
ignored.
|
|
216
|
+
The page load answers `lb-sort` and `lb-filters` first, so the rows land by
|
|
217
|
+
the order and the filters. When `url()` moves the page, the choices arrive
|
|
218
|
+
with the load at the new URL. `sort()` and `filters()`, like `url()`, take
|
|
219
|
+
columns whose values are strings, at least one of them; anything else is
|
|
220
|
+
reported on the server console and ignored.
|
|
217
221
|
|
|
218
222
|
### onChoices
|
|
219
223
|
|
|
220
|
-
`onChoices` runs each time the user
|
|
221
|
-
|
|
222
|
-
`onPageEnter` to restore, and answers nothing, by
|
|
223
|
-
returns lands. A page without it is not told.
|
|
224
|
+
`onChoices` runs each time the user changes the order or a filter, with the
|
|
225
|
+
query and its new `sort` or `filters`, as strings. It is how an application
|
|
226
|
+
keeps them for `onPageEnter` to restore, and answers nothing, by
|
|
227
|
+
convention. Whatever it returns lands. A page without it is not told.
|
|
224
228
|
|
|
225
229
|
### handlers
|
|
226
230
|
|
|
@@ -264,12 +268,6 @@ are one vocabulary:
|
|
|
264
268
|
| `lb-row-update` | `rowUpdate` | `query`, `key`, `values`, and `rows` from a form |
|
|
265
269
|
| `lb-row-delete` | `rowDelete` | `query`, `key` |
|
|
266
270
|
|
|
267
|
-
An `lb-row-update` or `lb-row-delete` carrying `keys` runs `rowUpdate` or
|
|
268
|
-
`rowDelete` once for each key, with that key, so a handler written for one
|
|
269
|
-
row serves several. The patches the runs return are laid together, and the
|
|
270
|
-
refresh set runs once. A `url()` returned for one of several rows is
|
|
271
|
-
reported and ignored. A declared request receives `keys` as it is.
|
|
272
|
-
|
|
273
271
|
`rows` holds the rows of a query nested in the form the request came from,
|
|
274
272
|
by query name, each with its `key` and the `values` of its own controls; see
|
|
275
273
|
[A form over a set of rows](./data-binding.md#a-form-over-a-set-of-rows).
|
|
@@ -199,7 +199,6 @@ interface HubRequest {
|
|
|
199
199
|
name: string;
|
|
200
200
|
query?: string;
|
|
201
201
|
key?: string;
|
|
202
|
-
keys?: string[];
|
|
203
202
|
values?: Record<string, string>;
|
|
204
203
|
rows?: Record<string, { key: string; values: Record<string, string> }[]>;
|
|
205
204
|
}
|
|
@@ -229,9 +228,9 @@ in `drop` are removed, and every other row is left alone. A `rows` item on
|
|
|
229
228
|
the answer that loads the page also carries the query's declared `order`
|
|
230
229
|
and `types`, which the hub keeps for every answer after it.
|
|
231
230
|
|
|
232
|
-
A
|
|
233
|
-
|
|
234
|
-
[
|
|
231
|
+
A sort or a filter is sent as `lb-row-update` for `lb-sort` or `lb-filters`,
|
|
232
|
+
keyed by the query's name, with the new order or filter as `values`; see
|
|
233
|
+
[Sort and filters](./data-binding.md#sort-and-filters).
|
|
235
234
|
|
|
236
235
|
`createHub(pages)` builds the `Hub`, which has two calls, both answering
|
|
237
236
|
with response items: `dataForPage(page, ctx, options)` for a page load, and
|