@loadbare/app 0.19.0 → 0.20.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 +28 -2
- package/dist/build/assemble.js.map +1 -1
- package/dist/core/lb-constants.d.ts +7 -2
- package/dist/core/lb-constants.d.ts.map +1 -1
- package/dist/core/lb-constants.js +30 -4
- package/dist/core/lb-constants.js.map +1 -1
- package/dist/hub/lb-apply.d.ts +21 -0
- package/dist/hub/lb-apply.d.ts.map +1 -1
- package/dist/hub/lb-apply.js +221 -30
- 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 +26 -6
- package/dist/hub/lb-hub.browser.js.map +1 -1
- package/docs/comparison.md +23 -13
- package/docs/opinions.md +2 -2
- package/docs/reference/builder.md +11 -2
- package/docs/reference/chrome.md +83 -9
- package/docs/reference/css.md +0 -1
- package/docs/reference/custom-elements.md +7 -28
- package/docs/reference/data-binding.md +320 -50
- package/docs/reference/names.md +258 -0
- package/docs/reference/overview.md +6 -0
- package/docs/reference/page-files.md +47 -10
- package/docs/reference/server.md +54 -1
- package/docs/reference/widgets.md +10 -1
- package/docs/testing.md +5 -1
- package/docs/tutorials/040-displaying-data.md +1 -1
- package/package.json +1 -1
- package/skills/loadbare-app/SKILL.md +26 -14
- package/skills/loadbare-app/references/builder.md +11 -2
- package/skills/loadbare-app/references/chrome.md +83 -9
- package/skills/loadbare-app/references/css.md +0 -1
- package/skills/loadbare-app/references/custom-elements.md +7 -28
- package/skills/loadbare-app/references/data-binding.md +320 -50
- package/skills/loadbare-app/references/names.md +258 -0
- package/skills/loadbare-app/references/overview.md +6 -0
- package/skills/loadbare-app/references/page-files.md +47 -10
- package/skills/loadbare-app/references/server.md +54 -1
- package/skills/loadbare-app/references/widgets.md +10 -1
- package/docs/TECHREF-1.0.md +0 -2267
- package/skills/loadbare-app/references/TECHREF-1.0.md +0 -2267
|
@@ -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
|
+
seventeen `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`,
|
|
@@ -54,6 +54,7 @@ each with its key, and permits the three requests on `roster`; see
|
|
|
54
54
|
| `lb-select` | A checkbox in a row template | Nothing: it selects its live row; see [Selecting rows](#selecting-rows) |
|
|
55
55
|
| `lb-request` | Any element | The request it sends when it commits |
|
|
56
56
|
| `lb-url-link` | An `<a>` | A link between pages; see [chrome](./chrome.md#links) |
|
|
57
|
+
| `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) |
|
|
57
58
|
| `lb-url-push` | An element with `lb-request` | A URL change that pushes a history entry |
|
|
58
59
|
| `lb-url-unknown` | A `<dialog>` in the chrome | The dialog for a URL that names no page |
|
|
59
60
|
|
|
@@ -66,8 +67,10 @@ builder writes a stamp, and a stylesheet or a custom element reads it.
|
|
|
66
67
|
| `lb-key-value` | The key of a live row, or of a `row` landed on an element |
|
|
67
68
|
| `lb-row-live` | The element is a live row |
|
|
68
69
|
| `lb-query-row-count` | The number of live rows an element shows |
|
|
70
|
+
| `lb-query-unsorted-count` | The number of them out of order; see [Rows the user is working in](#rows-the-user-is-working-in) |
|
|
71
|
+
| `lb-query-order` | The order placing them; see [Order](#order) |
|
|
69
72
|
| `lb-group-live`, `lb-group-column`, `lb-group-value` | A group, the column it breaks on, and its value; see [Groups](#groups) |
|
|
70
|
-
| `lb-row-created`, `lb-row-changed`, `lb-row-moved`, `lb-row-requested` | What happened to a row; see [What happened to a row](#what-happened-to-a-row) |
|
|
73
|
+
| `lb-row-created`, `lb-row-changed`, `lb-row-moved`, `lb-row-requested`, `lb-row-unsorted` | What happened to a row; see [What happened to a row](#what-happened-to-a-row) |
|
|
71
74
|
| `lb-row-leaving`, `lb-group-leaving` | A row or group on its way out |
|
|
72
75
|
| `lb-row-editing` | The row a form is pointed at; see [Editing a row in one form](#editing-a-row-in-one-form) |
|
|
73
76
|
| `lb-row-selected` | A row whose `lb-select` is ticked |
|
|
@@ -89,7 +92,8 @@ elements as the page needs.
|
|
|
89
92
|
|
|
90
93
|
What lands depends on the query's kind and on whether the element holds a
|
|
91
94
|
row template, which is the first `<template>` among its descendants outside
|
|
92
|
-
any nested `lb-query
|
|
95
|
+
any nested `lb-query`, or, when that template is a [group
|
|
96
|
+
template](#groups), the innermost template inside it:
|
|
93
97
|
|
|
94
98
|
| Kind | Row template | The hub |
|
|
95
99
|
|--------|--------------|----------------------------------------|
|
|
@@ -128,6 +132,9 @@ row's `account`:
|
|
|
128
132
|
`lb-column` on an element with `lb-query` is undefined unless the element is
|
|
129
133
|
a control.
|
|
130
134
|
|
|
135
|
+
A query that arrives with nowhere to land is reported to the console,
|
|
136
|
+
unless its name begins with `lb-`.
|
|
137
|
+
|
|
131
138
|
An element with `lb-column` and no ancestor row receives nothing. The hub
|
|
132
139
|
still gathers from it, so an insert form writes `lb-column` on controls that
|
|
133
140
|
no row fills.
|
|
@@ -143,6 +150,10 @@ no row fills.
|
|
|
143
150
|
| Any other custom element | `lb-column-value` only |
|
|
144
151
|
| Any other element | Its text content, and `lb-column-value` |
|
|
145
152
|
|
|
153
|
+
A column lands in one attribute besides: the `href` of a link carrying
|
|
154
|
+
`lb-url-parm` that names it; see
|
|
155
|
+
[A link from a row](./chrome.md#a-link-from-a-row).
|
|
156
|
+
|
|
146
157
|
A control is an `<input>`, `<select>` or `<textarea>`, or a form-associated
|
|
147
158
|
custom element with a `value` property that fires `change`. The hub sets a
|
|
148
159
|
control's `value`, and gathers it back under the same column. A custom
|
|
@@ -150,7 +161,9 @@ element that is not a control keeps the content the builder placed in it
|
|
|
150
161
|
from its element file, and renders `lb-column-value` itself; see
|
|
151
162
|
[Custom Elements](./custom-elements.md#receiving-a-value).
|
|
152
163
|
|
|
153
|
-
A file input receives nothing,
|
|
164
|
+
A file input receives nothing, not even `lb-column-value`, and the hub
|
|
165
|
+
reports it to the console and gathers nothing from it. A `<select>` with no
|
|
166
|
+
option for the value shows no selection.
|
|
154
167
|
|
|
155
168
|
The hub hands every value to the browser as the server sent it. What a
|
|
156
169
|
number, a date or a null looks like is decided in the query, or by a custom
|
|
@@ -212,7 +225,9 @@ places it immediately before the template:
|
|
|
212
225
|
The hub matches each row to a live row by its key. All rows decide
|
|
213
226
|
membership: a live row whose key did not arrive leaves. A patch changes only
|
|
214
227
|
the rows it names, and every other live row keeps its content. The hub
|
|
215
|
-
places
|
|
228
|
+
places live rows by the query's order, except that an edit from inside the
|
|
229
|
+
list leaves them where they stand; see [Order](#order) and
|
|
230
|
+
[Rows the user is working in](#rows-the-user-is-working-in). A row that
|
|
216
231
|
does not pass the user's filter is `hidden`; see [Filters](#filters).
|
|
217
232
|
|
|
218
233
|
A live row whose values arrive as it already shows them is not filled
|
|
@@ -221,7 +236,11 @@ what was typed, through a refresh and through a change of order. A row
|
|
|
221
236
|
whose values changed is filled whole, and its controls show what arrived.
|
|
222
237
|
|
|
223
238
|
A key is unique within a query. Two rows with one key in the same answer,
|
|
224
|
-
or two live rows showing one key, are reported on the console.
|
|
239
|
+
or two live rows showing one key, are reported on the console. A row
|
|
240
|
+
missing its key column is reported and not landed.
|
|
241
|
+
|
|
242
|
+
A live row already in the markup when the first answer lands is one of the
|
|
243
|
+
query's rows.
|
|
225
244
|
|
|
226
245
|
When the focus is in a live row that placing moves, the hub puts it back on
|
|
227
246
|
the same element and scrolls it into view. When that row leaves, or a
|
|
@@ -266,14 +285,81 @@ server's order places the rows:
|
|
|
266
285
|
</ul>
|
|
267
286
|
```
|
|
268
287
|
|
|
269
|
-
Values
|
|
270
|
-
|
|
271
|
-
|
|
288
|
+
| Values | Compare |
|
|
289
|
+
|----------------------|----------------------------------------------|
|
|
290
|
+
| Two numbers | Numerically |
|
|
291
|
+
| Two strings | As the user's language orders them |
|
|
292
|
+
| Two booleans | `false` before `true` |
|
|
293
|
+
| Two different types | Booleans, then numbers, then strings |
|
|
294
|
+
| `null` or missing | After everything ascending, first descending |
|
|
295
|
+
|
|
296
|
+
A number sent as a string sorts as a string, unless the query declares the
|
|
272
297
|
column's [type](./page-files.md#queries): a column declared `number` sorts
|
|
273
298
|
numerically whatever JSON type its values arrive as, and a value that is no
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
299
|
+
value of its declared type compares as `null` does. `readAs` in
|
|
300
|
+
`@loadbare/app/types` is the rule the hub applies.
|
|
301
|
+
|
|
302
|
+
The element carrying `lb-query` carries `lb-query-order`, the order
|
|
303
|
+
placing its rows as an order's text, the user's when one is chosen and
|
|
304
|
+
the server's otherwise. Rows with no order carry none.
|
|
305
|
+
|
|
306
|
+
Rows that compare equal keep the order they arrived in, a patch's new rows
|
|
307
|
+
after the rows already showing. A row moves only when the order
|
|
308
|
+
puts it somewhere else, so all rows landing again unchanged move nothing.
|
|
309
|
+
|
|
310
|
+
### Rows the user is working in
|
|
311
|
+
|
|
312
|
+
A landing that answers a request sent from inside a list moves none of that
|
|
313
|
+
list's rows. The request is from inside the list when the list is the
|
|
314
|
+
nearest element carrying `lb-query` around the element that sent it: a
|
|
315
|
+
control in a live row, or a ghost row. A form elsewhere on the page is not
|
|
316
|
+
inside the list. A user who changes a value sees the value change, and the
|
|
317
|
+
row stays where they were working:
|
|
318
|
+
|
|
319
|
+
| The answer | The row |
|
|
320
|
+
|------------------------------------------|---------------------------------------------------|
|
|
321
|
+
| Changes a column the order reads | Stays where it stands |
|
|
322
|
+
| Creates a row | Goes after the last row of its group, or last of all |
|
|
323
|
+
| Drops a row | Leaves |
|
|
324
|
+
| Changes a row so the filter hides it | Stays showing |
|
|
325
|
+
| Changes the column its group breaks on | Stays under its group's heading |
|
|
326
|
+
|
|
327
|
+
A patch and all rows answering the same edit land the same way. A row left
|
|
328
|
+
where the order or the filter would not leave it is stamped
|
|
329
|
+
`lb-row-unsorted`, and the element carrying `lb-query` carries
|
|
330
|
+
`lb-query-unsorted-count`, the number of such rows. Another element naming
|
|
331
|
+
the same query places its rows by the order: the user was not working
|
|
332
|
+
there.
|
|
333
|
+
|
|
334
|
+
The rows are placed by the order again, and every `lb-row-unsorted` is
|
|
335
|
+
cleared, when the user asks: when the page loads, when the user's order or
|
|
336
|
+
filter changes, or on `--lb-sort`. A button names the list with HTML's
|
|
337
|
+
`commandfor`, and a stylesheet shows it only while it has something to do:
|
|
338
|
+
|
|
339
|
+
```html
|
|
340
|
+
<div id="roster" lb-query="roster">
|
|
341
|
+
<button type="button" class="resort" commandfor="roster" command="--lb-sort">Re-sort</button>
|
|
342
|
+
<ul>
|
|
343
|
+
<template><li><input lb-column="name" lb-request="lb-row-update" /></li></template>
|
|
344
|
+
</ul>
|
|
345
|
+
</div>
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
```css
|
|
349
|
+
.resort {
|
|
350
|
+
display: none;
|
|
351
|
+
}
|
|
352
|
+
[lb-query-unsorted-count]:not([lb-query-unsorted-count="0"]) .resort {
|
|
353
|
+
display: revert;
|
|
354
|
+
}
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
`--lb-sort` places the rows the hub holds, with no round trip. Aimed at an
|
|
358
|
+
element that carries no `lb-query`, or shows no rows the hub holds, it is
|
|
359
|
+
reported to the console. A custom element that reorders rows by a request of
|
|
360
|
+
its own dispatches the same command on the list once the answer lands, with
|
|
361
|
+
`new CommandEvent("command", { command: "--lb-sort" })`: the user asked for
|
|
362
|
+
the move.
|
|
277
363
|
|
|
278
364
|
### Filters
|
|
279
365
|
|
|
@@ -292,7 +378,9 @@ its rows the user may filter, separated by commas. The column of
|
|
|
292
378
|
```
|
|
293
379
|
|
|
294
380
|
A row that does not pass every filter is `hidden`, and a ticked `lb-select`
|
|
295
|
-
in it is cleared. A
|
|
381
|
+
in it is cleared. A row an edit from inside the list changed stays showing
|
|
382
|
+
until the rows are placed again; see
|
|
383
|
+
[Rows the user is working in](#rows-the-user-is-working-in). A group whose rows are all hidden is hidden too
|
|
296
384
|
([miswart](./miswarts.md#rows-hidden-by-a-filter)). An empty
|
|
297
385
|
choice filters nothing.
|
|
298
386
|
|
|
@@ -323,6 +411,9 @@ The column's type is the one its query declares, if it declares one, and
|
|
|
323
411
|
its JSON type otherwise. A value that is not of the column's type, and a
|
|
324
412
|
column that is null or missing, pass only `!=`.
|
|
325
413
|
|
|
414
|
+
`parseFilter`, `passes` and `passesTerm` in `@loadbare/app/types` are the
|
|
415
|
+
rule the hub applies.
|
|
416
|
+
|
|
326
417
|
### Groups
|
|
327
418
|
|
|
328
419
|
A group is a run of rows sharing the order's leading term. Write a
|
|
@@ -343,19 +434,46 @@ template. The nth group template breaks on the order's nth term.
|
|
|
343
434
|
</ul>
|
|
344
435
|
```
|
|
345
436
|
|
|
346
|
-
The group
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
nested template is
|
|
437
|
+
The hub clones the group template where the order breaks, and the group's
|
|
438
|
+
contents land immediately before the clone of its nested template, so the
|
|
439
|
+
markup's nesting decides the shape:
|
|
440
|
+
|
|
441
|
+
| The nested template is | The group's contents land | Example |
|
|
442
|
+
|------------------------------|------------------------------------|-----------------------------------|
|
|
443
|
+
| Inside the heading's element | Inside it | `<tbody>`, `<li>`, `<details>` |
|
|
444
|
+
| Beside the heading | After the heading, as its siblings | A heading `<tr>` in one `<tbody>` |
|
|
445
|
+
|
|
446
|
+
`<tbody>` and `<optgroup>` do not nest, so a table's levels below the first
|
|
447
|
+
are heading rows beside their rows:
|
|
448
|
+
|
|
449
|
+
```html
|
|
450
|
+
<table lb-query="accounts">
|
|
451
|
+
<thead><tr><th>Account</th></tr></thead>
|
|
452
|
+
<template lb-group>
|
|
453
|
+
<tbody>
|
|
454
|
+
<tr><th scope="rowgroup" lb-column="category"></th></tr>
|
|
455
|
+
<template><tr><td lb-column="account_name"></td></tr></template>
|
|
456
|
+
</tbody>
|
|
457
|
+
</template>
|
|
458
|
+
</table>
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
Content after the nested template lands after the group's rows, which is
|
|
462
|
+
where a group's footer goes.
|
|
351
463
|
|
|
352
464
|
A heading is filled from its group's first row, so it may show a column
|
|
353
|
-
other than the one the group breaks on.
|
|
465
|
+
other than the one the group breaks on. A row an edit from inside the list
|
|
466
|
+
moved to another group stays under its old heading, and the heading shows
|
|
467
|
+
the row as it stood, until the rows are placed again. The hub stamps each top-level
|
|
354
468
|
element of a group with `lb-group-live`, `lb-group-column` and
|
|
355
469
|
`lb-group-value`. A row creates its group, and a group leaves with its last
|
|
356
470
|
row. When the order changes, a group whose run goes on is kept and moved,
|
|
357
471
|
and a group whose run ended leaves.
|
|
358
472
|
|
|
473
|
+
A group template with no nested template is reported to the console. More
|
|
474
|
+
group templates than the order has terms show each extra level as one
|
|
475
|
+
group, and are reported once.
|
|
476
|
+
|
|
359
477
|
### Aggregates
|
|
360
478
|
|
|
361
479
|
`lb-count`, `lb-sum="col"`, `lb-avg="col"`, `lb-min="col"` and
|
|
@@ -366,10 +484,24 @@ or of the whole list outside any group:
|
|
|
366
484
|
<tr><td><span lb-count></span> people</td><td lb-sum="salary"></td></tr>
|
|
367
485
|
```
|
|
368
486
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
487
|
+
| Attribute | Sets the element to |
|
|
488
|
+
|----------------|-----------------------------------------------------------|
|
|
489
|
+
| `lb-count` | The number of rows |
|
|
490
|
+
| `lb-sum="col"` | The sum of `col` |
|
|
491
|
+
| `lb-avg="col"` | The average of `col` |
|
|
492
|
+
| `lb-min="col"` | The least value of `col`, by the [order](#order)'s comparison |
|
|
493
|
+
| `lb-max="col"` | The greatest, likewise |
|
|
494
|
+
|
|
495
|
+
An aggregate lands as a column does, with `lb-column-value`. A sum and an
|
|
496
|
+
average are exact decimals, read from JSON numbers and from strings holding
|
|
497
|
+
a plain decimal, as Postgres sends `numeric`. A sum has as many places as
|
|
498
|
+
the most precise value, and an average up to two more. `null` and empty
|
|
499
|
+
values are left out, as SQL leaves them out, and any other value is left
|
|
500
|
+
out and reported once. The result lands unformatted.
|
|
501
|
+
|
|
502
|
+
An aggregate covers the rows showing, so a row a filter hides is left out.
|
|
503
|
+
Where the true total matters beyond what the page shows, have the server
|
|
504
|
+
answer it as a row.
|
|
373
505
|
|
|
374
506
|
### What happened to a row
|
|
375
507
|
|
|
@@ -381,13 +513,23 @@ Every change to a list is one a stylesheet can see:
|
|
|
381
513
|
| `lb-row-changed` | Its values changed when the hub last touched it |
|
|
382
514
|
| `lb-row-moved` | Its values changed, and it now stands elsewhere |
|
|
383
515
|
| `lb-row-requested` | `created`, `changed` or `moved` by this page's request |
|
|
516
|
+
| `lb-row-unsorted` | Stands where the order would not put it |
|
|
384
517
|
| `lb-row-leaving` | A row on its way out |
|
|
385
518
|
| `lb-group-leaving` | A group on its way out |
|
|
386
519
|
|
|
387
|
-
|
|
520
|
+
The hub touches a row when an answer names it. `lb-row-created`,
|
|
521
|
+
`lb-row-changed` and `lb-row-moved` are cleared when it next does, and one
|
|
522
|
+
applied again is removed and added as two changes, so an animation keyed to
|
|
523
|
+
it plays again. `lb-row-requested` is cleared at every landing of the row's
|
|
524
|
+
query, and set only by a landing that answers a request from the page.
|
|
525
|
+
`lb-row-unsorted` is a state, not an event: it stays until the rows are
|
|
526
|
+
placed by the order; see
|
|
527
|
+
[Rows the user is working in](#rows-the-user-is-working-in).
|
|
528
|
+
|
|
529
|
+
A row or a group that leaves loses `lb-row-live` or `lb-group-live`, takes
|
|
530
|
+
`lb-row-leaving` or `lb-group-leaving` and `inert`
|
|
388
531
|
([miswart](./miswarts.md#leaving-rows-are-inert)), and is removed once its
|
|
389
|
-
animations finish, at once when there are none.
|
|
390
|
-
cleared at every landing; the others when the hub next touches the row.
|
|
532
|
+
animations finish, at once when there are none.
|
|
391
533
|
|
|
392
534
|
A row is moved when its values changed and the rows whose values did not
|
|
393
535
|
change now stand around it differently. A row it passed is not stamped,
|
|
@@ -398,6 +540,11 @@ and a change of the user's order, which changes no values, stamps none.
|
|
|
398
540
|
[lb-row-leaving] { animation: depart 200ms forwards; }
|
|
399
541
|
```
|
|
400
542
|
|
|
543
|
+
A row never travels between its two places, since that takes measuring, and
|
|
544
|
+
measuring takes script. Scrolling to a row is script too: a custom element
|
|
545
|
+
reads `lb-row-requested` in
|
|
546
|
+
[`lbRowsLanded`](./custom-elements.md#holding-rows).
|
|
547
|
+
|
|
401
548
|
### What arrives later
|
|
402
549
|
|
|
403
550
|
The hub keeps each query's last answer until the page changes, with any
|
|
@@ -426,7 +573,9 @@ insert form above: it sits inside `lb-query="roster"` so its request is for
|
|
|
426
573
|
|
|
427
574
|
The hub stamps every element that holds a row template with
|
|
428
575
|
`lb-query-row-count`, the number of live rows it shows. A row a filter
|
|
429
|
-
hides is not counted.
|
|
576
|
+
hides is not counted. Beside it, `lb-query-unsorted-count` is the number of
|
|
577
|
+
rows out of order; see
|
|
578
|
+
[Rows the user is working in](#rows-the-user-is-working-in). An empty query is a stylesheet rule:
|
|
430
579
|
|
|
431
580
|
```html
|
|
432
581
|
<div lb-query="roster">
|
|
@@ -451,6 +600,39 @@ hides is not counted. An empty query is a stylesheet rule:
|
|
|
451
600
|
The element carrying `lb-query` is a `<div>` here rather than the `<ul>`, so
|
|
452
601
|
that the message is inside it and one rule reaches both.
|
|
453
602
|
|
|
603
|
+
### Master-detail
|
|
604
|
+
|
|
605
|
+
A master is a `row` query and its detail is a `rows` query, as two names
|
|
606
|
+
answered side by side. A column never holds rows.
|
|
607
|
+
|
|
608
|
+
```html
|
|
609
|
+
<section lb-query="invoice">
|
|
610
|
+
<h2 lb-column="number"></h2>
|
|
611
|
+
<span lb-column="customer"></span>
|
|
612
|
+
</section>
|
|
613
|
+
|
|
614
|
+
<table>
|
|
615
|
+
<tbody lb-query="invoiceLines">
|
|
616
|
+
<template><tr><td lb-column="item"></td><td lb-column="amount"></td></tr></template>
|
|
617
|
+
</tbody>
|
|
618
|
+
</table>
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
Many masters, each with its own detail, is one `rows` query of joined rows:
|
|
622
|
+
each detail row carries its master's columns. A [group template](#groups)
|
|
623
|
+
shows each master as a group, ordered by the master's key first.
|
|
624
|
+
|
|
625
|
+
A query nested in another query's row template receives the same rows in
|
|
626
|
+
every live row. That serves a picker offering the same choices on every
|
|
627
|
+
row, and is not a way to show a different detail per row; see
|
|
628
|
+
[What arrives later](#what-arrives-later).
|
|
629
|
+
|
|
630
|
+
Which master a page shows is a query parm, which a query reads off `ctx`,
|
|
631
|
+
since a query takes no argument from the browser; see
|
|
632
|
+
[Query parms](./chrome.md#query-parms). When a write creates or removes the
|
|
633
|
+
master, the handler moves the URL; see
|
|
634
|
+
[Moving the URL](./page-files.md#moving-the-url).
|
|
635
|
+
|
|
454
636
|
## Conditional rendering
|
|
455
637
|
|
|
456
638
|
A page holds every element it can show. Write `lb-show` on an element,
|
|
@@ -565,10 +747,14 @@ answers with response items, which land like any others.
|
|
|
565
747
|
| A control | `change` |
|
|
566
748
|
| Any other element | `click` |
|
|
567
749
|
|
|
568
|
-
A click inside an element carrying `lb-request` commits it
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
750
|
+
A click inside an element carrying `lb-request` commits it, as long as the
|
|
751
|
+
element is inside `<lb-hub>` and no interactive content lies between them.
|
|
752
|
+
Interactive content is HTML's: `<a href>`, `<button>`, `<input>` other than
|
|
753
|
+
hidden, `<select>`, `<textarea>`, `<label>`, `<details>`, `<iframe>`,
|
|
754
|
+
`<embed>`, `<audio controls>`, `<video controls>` and `<img usemap>`, plus
|
|
755
|
+
any form-associated custom element. A click on one of them belongs to it: a
|
|
756
|
+
click into an input inside a deletable row focuses the input and deletes
|
|
757
|
+
nothing.
|
|
572
758
|
|
|
573
759
|
A submit button with a form owner commits with its form. On `submit`, the
|
|
574
760
|
hub sends the submitter's `lb-request` when the submitter carries one, and
|
|
@@ -602,7 +788,10 @@ carrying `lb-request`:
|
|
|
602
788
|
|
|
603
789
|
The hub gathers from controls only, and skips a control that belongs to a
|
|
604
790
|
query nested inside the group, except that a form gathers the rows of a
|
|
605
|
-
query nested in its own; see [A form over a set of rows](#a-form-over-a-set-of-rows).
|
|
791
|
+
query nested in its own; see [A form over a set of rows](#a-form-over-a-set-of-rows).
|
|
792
|
+
An element carrying `lb-query` and `lb-column` both, such as a picker,
|
|
793
|
+
belongs to the row around it, and is gathered with it and sends for that
|
|
794
|
+
row's query. A form owner includes a control outside the
|
|
606
795
|
form that names it with the HTML `form` attribute, which is how a table row,
|
|
607
796
|
where a form cannot go, sends one:
|
|
608
797
|
|
|
@@ -674,8 +863,10 @@ query's name, in `rows`:
|
|
|
674
863
|
The list of deduction types lives only in the database: the nested query
|
|
675
864
|
answers it, and the form shows one input per row.
|
|
676
865
|
|
|
677
|
-
- Every live row of the nested query
|
|
678
|
-
empty value means, such as no deduction of that type,
|
|
866
|
+
- Every live row of the nested query that holds a control goes, whatever
|
|
867
|
+
its values. What an empty value means, such as no deduction of that type,
|
|
868
|
+
is the handler's. A picker's options hold no control, so a picker in the
|
|
869
|
+
form sends its own value and none of its rows.
|
|
679
870
|
- One level only. A query nested inside a nested row shows the same rows in
|
|
680
871
|
every row around it, so it is not gathered.
|
|
681
872
|
- An insert, an update and a declared request carry `rows`. A delete does
|
|
@@ -685,7 +876,9 @@ answers it, and the form shows one input per row.
|
|
|
685
876
|
- A live row gathers nothing nested, as before.
|
|
686
877
|
|
|
687
878
|
The handler for the form's query receives `rows` beside `values`, and writes
|
|
688
|
-
the master and its details together; see [crud](./page-files.md#crud).
|
|
879
|
+
the master and its details together; see [crud](./page-files.md#crud). The
|
|
880
|
+
server checks that `rows` holds string keys and string values by query, and
|
|
881
|
+
ignores a request whose `rows` does not.
|
|
689
882
|
|
|
690
883
|
A nested query answers once for the page, so its rows are the same wherever
|
|
691
884
|
they show. The form enters a new master with its details, or edits the
|
|
@@ -722,9 +915,14 @@ holds what a submit will gather:
|
|
|
722
915
|
</section>
|
|
723
916
|
```
|
|
724
917
|
|
|
725
|
-
The same holds for a request a custom element sends carrying `key: ""`.
|
|
726
|
-
|
|
727
|
-
|
|
918
|
+
The same holds for a request a custom element sends carrying `key: ""`. No
|
|
919
|
+
ancestor sees a request not sent, and it gets no `lb-request-done`. An
|
|
920
|
+
update or delete with no row around it at all has no key either, and that
|
|
921
|
+
is reported to the console.
|
|
922
|
+
|
|
923
|
+
A field the request already carries is its issuer's and is kept, so a
|
|
924
|
+
custom element that dispatches its own request with `values` is not
|
|
925
|
+
gathered over.
|
|
728
926
|
|
|
729
927
|
### Inserting, updating and deleting rows
|
|
730
928
|
|
|
@@ -741,6 +939,10 @@ The hub sends one of these only when it has what the table lists, and
|
|
|
741
939
|
otherwise reports to the console. An insert or an update that gathers
|
|
742
940
|
nothing is not sent.
|
|
743
941
|
|
|
942
|
+
For a query the hub serves, `lb-url` or `lb-choices`, the hub answers
|
|
943
|
+
`lb-row-update` itself, with no round trip; see
|
|
944
|
+
[Query parms](./chrome.md#query-parms) and [Choices](#choices).
|
|
945
|
+
|
|
744
946
|
A key comes from a live row, or from an element a `row` landed on, so all
|
|
745
947
|
three work against either kind:
|
|
746
948
|
|
|
@@ -804,11 +1006,13 @@ round trip, including columns no element in the table shows. The user
|
|
|
804
1006
|
edits a row they can see, so the row is on the page. A row that has to be
|
|
805
1007
|
fetched to be edited is another page, with that row as its master.
|
|
806
1008
|
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
form
|
|
810
|
-
|
|
811
|
-
|
|
1009
|
+
Pointing a form first empties it: every column it names lands as null, and
|
|
1010
|
+
the form resets, so each control returns to its default. Edit then lands
|
|
1011
|
+
the row on the form, stamps the form with the row's key, so the form's
|
|
1012
|
+
request carries it, and stamps the row `lb-row-editing`. New stamps an
|
|
1013
|
+
empty key, making the form [a row not yet entered](#a-row-not-yet-entered).
|
|
1014
|
+
Both focus the form's first control. The form's state is in its
|
|
1015
|
+
`lb-key-value` stamp:
|
|
812
1016
|
|
|
813
1017
|
| `lb-key-value` | The form is |
|
|
814
1018
|
|----------------|-----------------------------|
|
|
@@ -851,6 +1055,11 @@ landing again lands nothing on it, and what the user has typed stays.
|
|
|
851
1055
|
A button inside a form that carries a command is `type="button"`, or it
|
|
852
1056
|
submits the form instead.
|
|
853
1057
|
|
|
1058
|
+
A command the hub cannot carry out is reported to the console: Edit from
|
|
1059
|
+
outside a live row of the form's query, Edit for a key the hub holds no row
|
|
1060
|
+
for, and any of these three commands aimed at an element that is not a form
|
|
1061
|
+
carrying `lb-query`.
|
|
1062
|
+
|
|
854
1063
|
### Selecting rows
|
|
855
1064
|
|
|
856
1065
|
A checkbox carrying `lb-select` in a row template selects the live row it
|
|
@@ -927,7 +1136,7 @@ A button carries no value, so a declared request from one sends the values
|
|
|
927
1136
|
of the live row or form it sits in, and the server computes the rest.
|
|
928
1137
|
|
|
929
1138
|
A request name beginning with `lb-` that is not one of the three is refused
|
|
930
|
-
by the builder.
|
|
1139
|
+
by the builder in markup, and by the hub when a script dispatches it.
|
|
931
1140
|
|
|
932
1141
|
### Request state
|
|
933
1142
|
|
|
@@ -992,14 +1201,23 @@ submit, as for any invalid control, so the user edits before trying again.
|
|
|
992
1201
|
|
|
993
1202
|
A form-associated custom element takes a column's message when it has
|
|
994
1203
|
`setCustomValidity` and `reportValidity`; see
|
|
995
|
-
[Being a control](./custom-elements.md#being-a-control).
|
|
1204
|
+
[Being a control](./custom-elements.md#being-a-control). A request for
|
|
1205
|
+
several rows takes the whole-request message only. A column the request
|
|
1206
|
+
gathered no control for is reported to the console.
|
|
1207
|
+
|
|
1208
|
+
On the wire a refusal is status 422 with `{ refusal: { message?, columns? } }`;
|
|
1209
|
+
see [The data channel](./server.md#the-data-channel).
|
|
996
1210
|
|
|
997
1211
|
### The request event
|
|
998
1212
|
|
|
999
1213
|
The hub dispatches every request as a bubbling `lb-request` event from the
|
|
1000
1214
|
element that committed, with the request as its `detail`, before sending it.
|
|
1001
|
-
|
|
1002
|
-
|
|
1215
|
+
The hub completes the request on the event's way down, so every ancestor
|
|
1216
|
+
sees it whole on the way up. An ancestor may stop it, and the request is
|
|
1217
|
+
not sent: the event is not cancelable, so an interceptor calls
|
|
1218
|
+
`stopPropagation`, not `preventDefault`. That is how a confirmation wrapper
|
|
1219
|
+
works without the wrapped element knowing about it. A custom element may
|
|
1220
|
+
dispatch the event itself; see
|
|
1003
1221
|
[Sending a request](./custom-elements.md#sending-a-request).
|
|
1004
1222
|
|
|
1005
1223
|
Once the answer has landed, or the round trip has failed, the hub calls
|
|
@@ -1008,6 +1226,37 @@ then dispatches a bubbling `lb-request-done` event from the same element.
|
|
|
1008
1226
|
Both carry the request and what landed because of it, or the error; see
|
|
1009
1227
|
[Hearing how it turned out](./custom-elements.md#hearing-how-it-turned-out).
|
|
1010
1228
|
|
|
1229
|
+
### The round trip
|
|
1230
|
+
|
|
1231
|
+
A request the hub sends has ten seconds to come back. Past that the hub
|
|
1232
|
+
aborts it and treats it as a failure, since `fetch` imposes no deadline of
|
|
1233
|
+
its own. An application cannot change the deadline.
|
|
1234
|
+
|
|
1235
|
+
A round trip fails on a server error, on a network failure, or on that
|
|
1236
|
+
deadline, and all three stamp `lb-request-error` on the element that sent
|
|
1237
|
+
the request. A refusal is not a failure.
|
|
1238
|
+
|
|
1239
|
+
After a successful `lb-row-insert` gathered from a form, the hub resets the
|
|
1240
|
+
form, after it lands the response. A failed insert resets nothing, so the
|
|
1241
|
+
entry can be corrected. An `lb-row-update` resets nothing: the row it sent
|
|
1242
|
+
lands back on its controls.
|
|
1243
|
+
|
|
1244
|
+
A reset of any form, whether the hub's, a reset button's or a script's,
|
|
1245
|
+
returns its controls to their defaults, and the hub removes
|
|
1246
|
+
`lb-column-value` from each of them. A cancelled reset keeps both.
|
|
1247
|
+
|
|
1248
|
+
A page load that fails lands nothing and is reported to the console. A load
|
|
1249
|
+
started by a request for `lb-url` stamps the element that sent it, as any
|
|
1250
|
+
request stamps its element.
|
|
1251
|
+
|
|
1252
|
+
A response answers for the URL its request was sent from, path and query
|
|
1253
|
+
string both. One that returns after the URL has moved lands nothing, since
|
|
1254
|
+
it describes what the user is no longer looking at: a request's answer,
|
|
1255
|
+
including any `url()` it carries, and a page load overtaken by a newer one.
|
|
1256
|
+
A write whose answer is dropped this way has still happened. Its
|
|
1257
|
+
`lb-request-done` carries no items and no error, and an insert still resets
|
|
1258
|
+
its form.
|
|
1259
|
+
|
|
1011
1260
|
## The URL
|
|
1012
1261
|
|
|
1013
1262
|
The hub serves one query of its own, `lb-url`: one row holding the path, the
|
|
@@ -1056,7 +1305,9 @@ The developer writes `lb-` attributes in markup, and script never assigns
|
|
|
1056
1305
|
them. The builder checks the markup of the chrome and of every page, after
|
|
1057
1306
|
expansion, and refuses to build:
|
|
1058
1307
|
|
|
1059
|
-
- an `lb-` attribute that is not one of the
|
|
1308
|
+
- an `lb-` attribute that is not one of the seventeen the developer writes;
|
|
1309
|
+
`lb-exp-slot` and `lb-exp-template` are consumed by expansion and never
|
|
1310
|
+
reach the check
|
|
1060
1311
|
- `lb-request` naming an `lb-` request other than the three Loadbare provides
|
|
1061
1312
|
- `lb-query` naming a query the page does not declare; every page and the
|
|
1062
1313
|
chrome may name `lb-url` and `lb-choices`, and the chrome names no other
|
|
@@ -1067,6 +1318,9 @@ expansion, and refuses to build:
|
|
|
1067
1318
|
a form's own when the form carries `lb-query`, and otherwise the nearest
|
|
1068
1319
|
`lb-query` around the element
|
|
1069
1320
|
- `lb-url-link` on anything but an `<a>`
|
|
1321
|
+
- `lb-url-parm` on anything but an `<a>` carrying `lb-url-link`, naming no
|
|
1322
|
+
column, naming columns not separated by commas or one beginning `lb-`, or
|
|
1323
|
+
with no row around it
|
|
1070
1324
|
- `lb-url-push` on an element without `lb-request`
|
|
1071
1325
|
- `lb-url-unknown` on anything but a `<dialog>`, or outside `<lb-hub>`
|
|
1072
1326
|
- `lb-show` on a `<template>`, or on a row template's root
|
|
@@ -1076,8 +1330,24 @@ expansion, and refuses to build:
|
|
|
1076
1330
|
no column
|
|
1077
1331
|
- `lb-select` on anything but `<input type="checkbox">`, outside a row
|
|
1078
1332
|
template, or beside `lb-column` or `lb-request`
|
|
1079
|
-
- a `command` beginning `--lb-` that is not one of the
|
|
1080
|
-
- one of the
|
|
1333
|
+
- a `command` beginning `--lb-` that is not one of the four commands
|
|
1334
|
+
- one of the four commands with no `commandfor`
|
|
1335
|
+
- `lb-group` on anything but a `<template>`, or on one holding no
|
|
1336
|
+
`<template>` for its contents
|
|
1337
|
+
- an aggregate on a `<template>`, or any but `lb-count` naming no column
|
|
1338
|
+
- a chrome without exactly one `<lb-hub>` and exactly one `<main>`, a
|
|
1339
|
+
`<main>` outside `<lb-hub>`, or a `<main>` holding anything but whitespace
|
|
1340
|
+
- a page carrying an `<lb-hub>` or a `<main>`
|
|
1341
|
+
|
|
1342
|
+
The builder also reads the script of every custom element it ships, other
|
|
1343
|
+
than `<lb-hub>`, and refuses one that declares a method, accessor or field
|
|
1344
|
+
whose name is `lb`, a capital, and anything Loadbare does not call; see
|
|
1345
|
+
[Reserved methods](./names.md#reserved-methods).
|
|
1346
|
+
|
|
1347
|
+
`lb-column` with no ancestor row is allowed: the hub gathers from it.
|
|
1348
|
+
|
|
1349
|
+
Script never assigns an `lb-` attribute, so the markup states every one
|
|
1350
|
+
that exists, and checking the markup is sound.
|
|
1081
1351
|
|
|
1082
1352
|
To know what each page declares, the builder loads its `.queries.ts` and
|
|
1083
1353
|
`.requests.ts` modules, so their import-time code runs during the build, as
|