@loadbare/app 0.12.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 +87 -1
- package/dist/build/assemble.js.map +1 -1
- package/dist/build/cli.js +2 -1
- package/dist/build/cli.js.map +1 -1
- package/dist/build/elements.d.ts +9 -1
- package/dist/build/elements.d.ts.map +1 -1
- package/dist/build/elements.js +50 -0
- package/dist/build/elements.js.map +1 -1
- package/dist/build/origins.d.ts +2 -0
- package/dist/build/origins.d.ts.map +1 -1
- package/dist/build/origins.js +1 -1
- package/dist/build/origins.js.map +1 -1
- package/dist/core/lb-constants.d.ts +34 -1
- package/dist/core/lb-constants.d.ts.map +1 -1
- package/dist/core/lb-constants.js +105 -0
- package/dist/core/lb-constants.js.map +1 -1
- package/dist/core/lb-types.d.ts +74 -18
- package/dist/core/lb-types.d.ts.map +1 -1
- package/dist/core/lb-types.js +74 -11
- package/dist/core/lb-types.js.map +1 -1
- package/dist/hub/lb-apply.d.ts +57 -18
- package/dist/hub/lb-apply.d.ts.map +1 -1
- package/dist/hub/lb-apply.js +661 -63
- 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 +400 -33
- package/dist/hub/lb-hub.browser.js.map +1 -1
- package/dist/server/lb-express.d.ts +19 -7
- package/dist/server/lb-express.d.ts.map +1 -1
- package/dist/server/lb-express.js +62 -26
- package/dist/server/lb-express.js.map +1 -1
- package/dist/server/lb-server.d.ts +80 -11
- package/dist/server/lb-server.d.ts.map +1 -1
- package/dist/server/lb-server.js +185 -33
- package/dist/server/lb-server.js.map +1 -1
- package/docs/TECHREF-1.0.md +584 -111
- package/docs/comparison.md +17 -13
- package/docs/possible-ideas.md +308 -0
- package/docs/reference/chrome.md +7 -1
- package/docs/reference/custom-elements.md +134 -39
- package/docs/reference/data-binding.md +405 -17
- package/docs/reference/page-files.md +101 -19
- package/docs/reference/server.md +24 -0
- package/docs/reference/widgets.md +118 -25
- package/docs/roadmap.md +17 -6
- package/docs/testing.md +21 -10
- package/package.json +2 -3
- package/skills/loadbare-app/SKILL.md +92 -30
- package/skills/loadbare-app/references/TECHREF-1.0.md +584 -111
- package/skills/loadbare-app/references/chrome.md +7 -1
- package/skills/loadbare-app/references/custom-elements.md +134 -39
- package/skills/loadbare-app/references/data-binding.md +405 -17
- package/skills/loadbare-app/references/page-files.md +101 -19
- package/skills/loadbare-app/references/server.md +24 -0
- package/skills/loadbare-app/references/widgets.md +118 -25
|
@@ -121,6 +121,7 @@ no row fills.
|
|
|
121
121
|
| Element | Receives the value as |
|
|
122
122
|
|------------------------------------------------------|-----------------------------------------|
|
|
123
123
|
| `<input>`, `<select>`, `<textarea>` | Its `value`, and `lb-column-value` |
|
|
124
|
+
| `<input type="checkbox">` | Its `checked`, and `lb-column-value` |
|
|
124
125
|
| A form-associated custom element with `value` | Its `value`, and `lb-column-value` |
|
|
125
126
|
| Any other custom element | `lb-column-value` only |
|
|
126
127
|
| Any other element | Its text content, and `lb-column-value` |
|
|
@@ -132,12 +133,26 @@ element that is not a control keeps the content the builder placed in it
|
|
|
132
133
|
from its element file, and renders `lb-column-value` itself; see
|
|
133
134
|
[Custom Elements](./custom-elements.md#receiving-a-value).
|
|
134
135
|
|
|
135
|
-
A
|
|
136
|
-
|
|
136
|
+
A radio button and a file input receive nothing, and the hub reports it to
|
|
137
|
+
the console.
|
|
137
138
|
|
|
138
139
|
The hub hands every value to the browser as the server sent it. What a
|
|
139
140
|
number, a date or a null looks like is decided in the query.
|
|
140
141
|
|
|
142
|
+
### Checkboxes
|
|
143
|
+
|
|
144
|
+
A checkbox is a control. It is checked when its column is anything but
|
|
145
|
+
`false` or null, and it sends `"true"` or `"false"`:
|
|
146
|
+
|
|
147
|
+
```html
|
|
148
|
+
<input type="checkbox" lb-column="active" lb-request="lb-row-update" />
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Checked follows the rule `lb-show` follows, so a query spells a flag as a
|
|
152
|
+
boolean, and the string `"false"` is checked. Unchecked sends `"false"`
|
|
153
|
+
rather than nothing, so a flag can be set back. The checkbox's `value`
|
|
154
|
+
attribute means nothing to the hub.
|
|
155
|
+
|
|
141
156
|
### Rows
|
|
142
157
|
|
|
143
158
|
Write a `<template>` inside the element carrying `lb-query`, holding one
|
|
@@ -153,9 +168,9 @@ places it immediately before the template:
|
|
|
153
168
|
```
|
|
154
169
|
|
|
155
170
|
The hub matches each row to a live row by its key. All rows decide
|
|
156
|
-
membership
|
|
157
|
-
|
|
158
|
-
|
|
171
|
+
membership: a live row whose key did not arrive leaves. A patch changes only
|
|
172
|
+
the rows it names, and every other live row keeps its content. The hub
|
|
173
|
+
places every live row by the query's order; see [Order](#order).
|
|
159
174
|
|
|
160
175
|
A key is unique within a query. Two rows with one key in the same answer,
|
|
161
176
|
or two live rows showing one key, are reported on the console.
|
|
@@ -163,10 +178,101 @@ or two live rows showing one key, are reported on the console.
|
|
|
163
178
|
A live row's root counts as a column when it carries `lb-column`, which is
|
|
164
179
|
how an `<option>`, whose content is text, shows the column it is.
|
|
165
180
|
|
|
166
|
-
A custom element that carries `lb-query` and a row template
|
|
167
|
-
|
|
168
|
-
[
|
|
169
|
-
|
|
181
|
+
A custom element that carries `lb-query` and a row template reacts to the
|
|
182
|
+
rows once they land; see [Holding rows](./custom-elements.md#holding-rows)
|
|
183
|
+
and [The Basic Widget Library](./widgets.md).
|
|
184
|
+
|
|
185
|
+
### Order
|
|
186
|
+
|
|
187
|
+
A `rows` query declares its order with the query, as columns separated by
|
|
188
|
+
commas, each descending when written after `-`:
|
|
189
|
+
|
|
190
|
+
```ts
|
|
191
|
+
roster: rows("id", (ctx) => ctx.db.members(), { order: "team,name" }),
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
The query parm `lb-order-<query>` replaces it for that query, so a control
|
|
195
|
+
inside `lb-query="lb-url"` writing that parm re-sorts the rows the hub
|
|
196
|
+
already has, with no round trip. With no order, rows show in the order they
|
|
197
|
+
arrived, and a patch's new rows go last.
|
|
198
|
+
|
|
199
|
+
Values compare by their JSON type: numbers numerically, strings as the
|
|
200
|
+
user's language orders them, `false` before `true`, and `null` last. A
|
|
201
|
+
number sent as a string sorts as a string. Rows that compare equal keep the
|
|
202
|
+
order they arrived in. A row moves only when the order puts it somewhere
|
|
203
|
+
else.
|
|
204
|
+
|
|
205
|
+
A query that pages or limits its rows reads the parm itself and declares
|
|
206
|
+
`serverSortedByUrl: true`, so a change of order loads the page again.
|
|
207
|
+
|
|
208
|
+
### Groups
|
|
209
|
+
|
|
210
|
+
A group is a run of rows sharing the order's leading term. Write a
|
|
211
|
+
`<template lb-group>` where the row template goes, holding the group's
|
|
212
|
+
heading and one nested `<template>`: the next group template, or the row
|
|
213
|
+
template. The nth group template breaks on the order's nth term.
|
|
214
|
+
|
|
215
|
+
```html
|
|
216
|
+
<ul lb-query="roster">
|
|
217
|
+
<template lb-group>
|
|
218
|
+
<li>
|
|
219
|
+
<h3 lb-column="team"></h3>
|
|
220
|
+
<ul>
|
|
221
|
+
<template><li lb-column="name"></li></template>
|
|
222
|
+
</ul>
|
|
223
|
+
</li>
|
|
224
|
+
</template>
|
|
225
|
+
</ul>
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
The group's contents land immediately before its nested template. When that
|
|
229
|
+
template is inside the heading's element, the contents land inside it; when
|
|
230
|
+
it is beside the heading, they land after it. `<tbody>` and `<optgroup>` do
|
|
231
|
+
not nest, so a table's deeper levels are heading rows. Content after the
|
|
232
|
+
nested template is the group's footer.
|
|
233
|
+
|
|
234
|
+
A heading is filled from its group's first row, so it may show a column
|
|
235
|
+
other than the one the group breaks on. The hub stamps each top-level
|
|
236
|
+
element of a group with `lb-group-live`, `lb-group-column` and
|
|
237
|
+
`lb-group-value`. A row creates its group, and a group leaves with its last
|
|
238
|
+
row.
|
|
239
|
+
|
|
240
|
+
### Aggregates
|
|
241
|
+
|
|
242
|
+
`lb-count`, `lb-sum="col"`, `lb-avg="col"`, `lb-min="col"` and
|
|
243
|
+
`lb-max="col"` set an element from the rows of the nearest group around it,
|
|
244
|
+
or of the whole list outside any group:
|
|
245
|
+
|
|
246
|
+
```html
|
|
247
|
+
<tr><td><span lb-count></span> people</td><td lb-sum="salary"></td></tr>
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
A sum and an average are exact, read from JSON numbers and from strings
|
|
251
|
+
holding a plain decimal. `null` and empty values are left out. The result
|
|
252
|
+
lands unformatted, and covers the rows the browser holds.
|
|
253
|
+
|
|
254
|
+
### What happened to a row
|
|
255
|
+
|
|
256
|
+
Every change to a list is one a stylesheet can see:
|
|
257
|
+
|
|
258
|
+
| Attribute | Means |
|
|
259
|
+
| ------------------ | ------------------------------------------------------ |
|
|
260
|
+
| `lb-row-created` | Created when the hub last touched the row |
|
|
261
|
+
| `lb-row-changed` | Its values changed when the hub last touched it |
|
|
262
|
+
| `lb-row-moved` | The order put it somewhere else when last touched |
|
|
263
|
+
| `lb-row-requested` | `created`, `changed` or `moved` by this page's request |
|
|
264
|
+
| `lb-row-leaving` | A row on its way out |
|
|
265
|
+
| `lb-group-leaving` | A group on its way out |
|
|
266
|
+
|
|
267
|
+
A row that leaves loses `lb-row-live`, takes `inert`, and is removed once
|
|
268
|
+
its animations finish, at once when there are none. A moved row moves, and
|
|
269
|
+
a copy stays behind where it was, leaving. `lb-row-requested` is cleared at
|
|
270
|
+
every landing; the others when the hub next touches the row.
|
|
271
|
+
|
|
272
|
+
```css
|
|
273
|
+
[lb-row-created] { animation: arrive 200ms; }
|
|
274
|
+
[lb-row-leaving] { animation: depart 200ms forwards; }
|
|
275
|
+
```
|
|
170
276
|
|
|
171
277
|
### What arrives later
|
|
172
278
|
|
|
@@ -174,16 +280,14 @@ The hub keeps each query's last answer until the page changes, with any
|
|
|
174
280
|
patch since applied to it. An element that names a query and arrives after
|
|
175
281
|
that query's answer is filled from what was kept, at the end of the landing
|
|
176
282
|
that follows its arrival. Such an element is a picker in a new live row, or
|
|
177
|
-
scaffolding
|
|
283
|
+
scaffolding around rows, such as a group's heading or a ghost row. So
|
|
178
284
|
a query nested in another query's rows need not land again, or land after
|
|
179
285
|
the outer query, for a new outer row to show its choices.
|
|
180
286
|
|
|
181
287
|
A custom element the builder shipped absent has not upgraded while its
|
|
182
|
-
`lb-show` column is off
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
table that groups its rows can sit under `lb-show`. See
|
|
186
|
-
[Holding rows](./custom-elements.md#holding-rows).
|
|
288
|
+
`lb-show` column is off. When the column first turns on and the element
|
|
289
|
+
upgrades, the hub lands the kept answer on it again, so its `lbRowsLanded`
|
|
290
|
+
runs. See [Holding rows](./custom-elements.md#holding-rows).
|
|
187
291
|
|
|
188
292
|
Nothing is answered from what the hub kept: a request always goes to the
|
|
189
293
|
server, and a query re-runs only when a response names it. A patch that
|
|
@@ -325,7 +429,8 @@ Every request has one shape:
|
|
|
325
429
|
```
|
|
326
430
|
|
|
327
431
|
The hub takes `query`, `key` and `values` from where the element sits, and
|
|
328
|
-
sends each when it has one.
|
|
432
|
+
sends each when it has one. A request acting on several rows carries `keys`
|
|
433
|
+
in place of `key`; see [Selecting rows](#selecting-rows). The server runs the handler for the name and
|
|
329
434
|
answers with response items, which land like any others.
|
|
330
435
|
|
|
331
436
|
### Committing
|
|
@@ -372,7 +477,8 @@ carrying `lb-request`:
|
|
|
372
477
|
4. Otherwise: every control whose form owner is the element's form owner.
|
|
373
478
|
|
|
374
479
|
The hub gathers from controls only, and skips a control that belongs to a
|
|
375
|
-
query nested inside the group
|
|
480
|
+
query nested inside the group, except that a form gathers the rows of a
|
|
481
|
+
query nested in its own; see [A form over a set of rows](#a-form-over-a-set-of-rows). A form owner includes a control outside the
|
|
376
482
|
form that names it with the HTML `form` attribute, which is how a table row,
|
|
377
483
|
where a form cannot go, sends one:
|
|
378
484
|
|
|
@@ -403,6 +509,99 @@ ancestor `lb-query` and row of the element carrying `lb-request` instead.
|
|
|
403
509
|
Controls gathered from two different queries are an error, and the hub
|
|
404
510
|
sends nothing.
|
|
405
511
|
|
|
512
|
+
### A form over a set of rows
|
|
513
|
+
|
|
514
|
+
A form gathers the live rows of a query nested in its own query as well as
|
|
515
|
+
its own controls: a master and its details, entered together. Each nested
|
|
516
|
+
row goes as its key and the values of its own controls, under the nested
|
|
517
|
+
query's name, in `rows`:
|
|
518
|
+
|
|
519
|
+
```html
|
|
520
|
+
<form lb-query="paychecks" lb-request="lb-row-insert">
|
|
521
|
+
<input lb-column="pay_date" type="date" />
|
|
522
|
+
<table>
|
|
523
|
+
<tbody lb-query="deduction_types">
|
|
524
|
+
<template>
|
|
525
|
+
<tr>
|
|
526
|
+
<td lb-column="label"></td>
|
|
527
|
+
<td><input lb-column="amount" /></td>
|
|
528
|
+
</tr>
|
|
529
|
+
</template>
|
|
530
|
+
</tbody>
|
|
531
|
+
</table>
|
|
532
|
+
<button type="submit">Save</button>
|
|
533
|
+
</form>
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
```json
|
|
537
|
+
{
|
|
538
|
+
"name": "lb-row-insert",
|
|
539
|
+
"query": "paychecks",
|
|
540
|
+
"values": { "pay_date": "2026-10-02" },
|
|
541
|
+
"rows": {
|
|
542
|
+
"deduction_types": [
|
|
543
|
+
{ "key": "401k", "values": { "amount": "50" } },
|
|
544
|
+
{ "key": "dental", "values": { "amount": "" } }
|
|
545
|
+
]
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
The list of deduction types lives only in the database: the nested query
|
|
551
|
+
answers it, and the form shows one input per row.
|
|
552
|
+
|
|
553
|
+
- Every live row of the nested query goes, whatever its values. What an
|
|
554
|
+
empty value means, such as no deduction of that type, is the handler's.
|
|
555
|
+
- One level only. A query nested inside a nested row shows the same rows in
|
|
556
|
+
every row around it, so it is not gathered.
|
|
557
|
+
- An insert, an update and a declared request carry `rows`. A delete does
|
|
558
|
+
not.
|
|
559
|
+
- A form whose only controls are in nested rows still sends, for its own
|
|
560
|
+
query, with empty `values`.
|
|
561
|
+
- A live row gathers nothing nested, as before.
|
|
562
|
+
|
|
563
|
+
The handler for the form's query receives `rows` beside `values`, and writes
|
|
564
|
+
the master and its details together; see [crud](./page-files.md#crud).
|
|
565
|
+
|
|
566
|
+
A nested query answers once for the page, so its rows are the same wherever
|
|
567
|
+
they show. The form enters a new master with its details, or edits the
|
|
568
|
+
master the page shows, whose details the nested query reads from the same
|
|
569
|
+
query parm. A form [pointed at a row](#editing-a-row-in-one-form) fills its
|
|
570
|
+
own controls from that row; its nested rows stay the nested query's answer.
|
|
571
|
+
|
|
572
|
+
### A row not yet entered
|
|
573
|
+
|
|
574
|
+
A row whose key is empty is a new one, not yet entered. It arises two ways:
|
|
575
|
+
a `row` query answers with an empty key, as one showing the master a query
|
|
576
|
+
parm names does when the parm is empty, or New points a form (see
|
|
577
|
+
[Editing a row in one form](#editing-a-row-in-one-form)). Either way the
|
|
578
|
+
element carries `lb-key-value=""`.
|
|
579
|
+
|
|
580
|
+
| Request | From a row not yet entered |
|
|
581
|
+
|------------------|---------------------------------------|
|
|
582
|
+
| `lb-row-insert` | Sent, with no `key` |
|
|
583
|
+
| A declared one | Sent, with no `key` |
|
|
584
|
+
| `lb-row-update` | Not sent: there is nothing to update |
|
|
585
|
+
| `lb-row-delete` | Not sent: there is nothing to delete |
|
|
586
|
+
|
|
587
|
+
An update or delete not sent is the row's state, not a mistake, and nothing
|
|
588
|
+
is reported. So a control that saves its own column with
|
|
589
|
+
`lb-request="lb-row-update"` saves on a row on record, and on a new row only
|
|
590
|
+
holds what a submit will gather:
|
|
591
|
+
|
|
592
|
+
```html
|
|
593
|
+
<section lb-query="account">
|
|
594
|
+
<form id="account-form">
|
|
595
|
+
<input lb-column="name" lb-request="lb-row-update" />
|
|
596
|
+
</form>
|
|
597
|
+
<button type="submit" form="account-form" lb-request="lb-row-insert">Save new</button>
|
|
598
|
+
</section>
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
The same holds for a request a custom element sends carrying `key: ""`.
|
|
602
|
+
An update or delete with no row around it at all has no key either, and
|
|
603
|
+
that is reported to the console.
|
|
604
|
+
|
|
406
605
|
### Inserting, updating and deleting rows
|
|
407
606
|
|
|
408
607
|
Loadbare provides three requests. Each runs the handler the page declares
|
|
@@ -439,6 +638,152 @@ failed insert leaves the entry for the user to correct.
|
|
|
439
638
|
Leave `lb-request` off a control inside a form or a live row that sends its
|
|
440
639
|
own update, or the same edit is written twice.
|
|
441
640
|
|
|
641
|
+
### Editing a row in one form
|
|
642
|
+
|
|
643
|
+
A table, or any other set of rows, that the user edits or adds to has one
|
|
644
|
+
form on the page, naming the same query. It sits anywhere, outside every
|
|
645
|
+
row. Buttons point it with HTML's `commandfor` and `command`:
|
|
646
|
+
|
|
647
|
+
| Command | On a button | The hub |
|
|
648
|
+
|----------------|-------------------------------------|---------------------------------------------|
|
|
649
|
+
| `--lb-edit` | In a live row of the form's query | Fills the form from that row, keyed by it |
|
|
650
|
+
| `--lb-new` | Anywhere | Starts the form empty, for an insert |
|
|
651
|
+
| `--lb-release` | Anywhere | Lets the form go without saving |
|
|
652
|
+
|
|
653
|
+
HTML requires a custom command to begin with `--`.
|
|
654
|
+
|
|
655
|
+
```html
|
|
656
|
+
<tbody lb-query="paychecks">
|
|
657
|
+
<template>
|
|
658
|
+
<tr>
|
|
659
|
+
<td lb-column="pay_date"></td>
|
|
660
|
+
<td lb-column="gross"></td>
|
|
661
|
+
<td><button type="button" commandfor="paycheck" command="--lb-edit">Edit</button></td>
|
|
662
|
+
</tr>
|
|
663
|
+
</template>
|
|
664
|
+
</tbody>
|
|
665
|
+
<button type="button" commandfor="paycheck" command="--lb-new">New</button>
|
|
666
|
+
|
|
667
|
+
<dialog>
|
|
668
|
+
<form id="paycheck" lb-query="paychecks" lb-request="lb-row-update">
|
|
669
|
+
<input lb-column="pay_date" type="date" />
|
|
670
|
+
<input lb-column="gross" />
|
|
671
|
+
<button type="submit">Save</button>
|
|
672
|
+
<button type="submit" lb-request="lb-row-insert">Save new</button>
|
|
673
|
+
<button type="button" commandfor="paycheck" command="--lb-release">Cancel</button>
|
|
674
|
+
</form>
|
|
675
|
+
</dialog>
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
Edit fills the form from the row as the hub already holds it, with no
|
|
679
|
+
round trip, including columns no element in the table shows. The user
|
|
680
|
+
edits a row they can see, so the row is on the page. A row that has to be
|
|
681
|
+
fetched to be edited is another page, with that row as its master.
|
|
682
|
+
|
|
683
|
+
The hub stamps the form with the row's key, so the form's request carries
|
|
684
|
+
it, and stamps the row `lb-row-editing`. New stamps an empty key, making the
|
|
685
|
+
form [a row not yet entered](#a-row-not-yet-entered), and resets every
|
|
686
|
+
control to its default. The form's state is in its `lb-key-value`
|
|
687
|
+
stamp:
|
|
688
|
+
|
|
689
|
+
| `lb-key-value` | The form is |
|
|
690
|
+
|----------------|-----------------------------|
|
|
691
|
+
| A key | Editing that row |
|
|
692
|
+
| Empty | Entering a new row |
|
|
693
|
+
| Absent | Not in use |
|
|
694
|
+
|
|
695
|
+
A stylesheet shows Save or Save new by it:
|
|
696
|
+
|
|
697
|
+
```css
|
|
698
|
+
form[lb-key-value=""] [type="submit"]:not([lb-request]),
|
|
699
|
+
form:not([lb-key-value=""]) [lb-request="lb-row-insert"] {
|
|
700
|
+
display: none;
|
|
701
|
+
}
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
An `lb-show` in the form reads from the row it was pointed at. With no row,
|
|
705
|
+
every column is null, so `lb-show="!id"` shows only while entering a new
|
|
706
|
+
row.
|
|
707
|
+
|
|
708
|
+
A successful request from the form lets it go, as Cancel does: the form
|
|
709
|
+
empties, its controls return to their defaults, and the stamps go. A failed
|
|
710
|
+
one leaves the form as the user had it, to correct.
|
|
711
|
+
|
|
712
|
+
Inside a `<dialog>`, Edit and New open the dialog modally, and letting go
|
|
713
|
+
closes it. The dialog closing in any way HTML closes one lets the form go:
|
|
714
|
+
Escape, `command="close"`, or `method="dialog"`. A form in no dialog opens
|
|
715
|
+
nothing. It is always showing, as a detail panel beside the table is, or a
|
|
716
|
+
stylesheet shows it while it has a key:
|
|
717
|
+
|
|
718
|
+
```css
|
|
719
|
+
form:not([lb-key-value]) {
|
|
720
|
+
display: none;
|
|
721
|
+
}
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
The form names a `rows` query and holds no row template, so the query
|
|
725
|
+
landing again lands nothing on it, and what the user has typed stays.
|
|
726
|
+
|
|
727
|
+
A button inside a form that carries a command is `type="button"`, or it
|
|
728
|
+
submits the form instead.
|
|
729
|
+
|
|
730
|
+
### Selecting rows
|
|
731
|
+
|
|
732
|
+
A checkbox carrying `lb-select` in a row template selects the live row it
|
|
733
|
+
sits in. It is not a column: it carries no `lb-column`, lands nothing and
|
|
734
|
+
is not gathered. The hub stamps the row `lb-row-selected` while it is
|
|
735
|
+
ticked.
|
|
736
|
+
|
|
737
|
+
A request for the query that names no one row then acts on the rows
|
|
738
|
+
selected, and carries their keys as `keys`:
|
|
739
|
+
|
|
740
|
+
```html
|
|
741
|
+
<tbody lb-query="transactions">
|
|
742
|
+
<template>
|
|
743
|
+
<tr>
|
|
744
|
+
<td><input type="checkbox" lb-select lb-show="selecting" /></td>
|
|
745
|
+
<td lb-column="description"></td>
|
|
746
|
+
<td lb-column="amount"></td>
|
|
747
|
+
</tr>
|
|
748
|
+
</template>
|
|
749
|
+
</tbody>
|
|
750
|
+
|
|
751
|
+
<form lb-query="transactions" lb-request="lb-row-update">
|
|
752
|
+
<lb-picker lb-query="accounts" lb-column="acct" exp-label="Account" exp-column="name"></lb-picker>
|
|
753
|
+
<button type="submit">Apply</button>
|
|
754
|
+
<button type="button" lb-request="lb-row-delete">Delete</button>
|
|
755
|
+
</form>
|
|
756
|
+
```
|
|
757
|
+
|
|
758
|
+
```json
|
|
759
|
+
{ "name": "lb-row-update", "query": "transactions", "keys": ["4", "9"], "values": { "acct": "12" } }
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
| Request | With rows selected | With none ticked |
|
|
763
|
+
|------------------|----------------------------------------|----------------------|
|
|
764
|
+
| `lb-row-update` | Sent with `keys` | Not sent |
|
|
765
|
+
| `lb-row-delete` | Sent with `keys` | Not sent |
|
|
766
|
+
| A declared one | Sent with `keys` | Sent with `keys: []` |
|
|
767
|
+
| `lb-row-insert` | Sent as ever; the selection is not its | Sent as ever |
|
|
768
|
+
|
|
769
|
+
An update or delete with nothing ticked has nothing to act on, and nothing
|
|
770
|
+
is reported. A request from inside a row still names that row alone. The
|
|
771
|
+
server runs the page's `rowUpdate` or `rowDelete` once for each key, as for
|
|
772
|
+
each row alone, and refreshes once; see [crud](./page-files.md#crud).
|
|
773
|
+
|
|
774
|
+
After the request succeeds, the hub clears the selection. A failed one
|
|
775
|
+
leaves it, to try again.
|
|
776
|
+
|
|
777
|
+
Only a checkbox that is showing counts. Turning a selector off with
|
|
778
|
+
`lb-show` also clears its tick, so leaving a selecting mode abandons the
|
|
779
|
+
selection rather than keeping it out of sight. With every selector off, a
|
|
780
|
+
request for the query is an ordinary one again.
|
|
781
|
+
|
|
782
|
+
Which rows are selected, and whether the page is in a selecting mode, is
|
|
783
|
+
interaction state. A mode the URL keeps, such as `?selecting=1`, reaches
|
|
784
|
+
the rows as a column the query computes from the parm, which `lb-show`
|
|
785
|
+
reads.
|
|
786
|
+
|
|
442
787
|
### Declared requests
|
|
443
788
|
|
|
444
789
|
A request name the page declares under `handlers` runs the application's
|
|
@@ -468,6 +813,7 @@ The hub stamps the element that committed:
|
|
|
468
813
|
|----------------------|-----------------------------------------------|
|
|
469
814
|
| `lb-request-pending` | The round trip is in flight |
|
|
470
815
|
| `lb-request-error` | The round trip failed, until the next request |
|
|
816
|
+
| `lb-request-refused` | The handler refused it; see [Refusals](#refusals) |
|
|
471
817
|
|
|
472
818
|
`lb-request-error` covers a non-2xx response, a network failure and a
|
|
473
819
|
timeout alike. The hub aborts a round trip after ten seconds, and sets
|
|
@@ -485,6 +831,44 @@ pending button is already disabled and a stylesheet only shows it:
|
|
|
485
831
|
}
|
|
486
832
|
```
|
|
487
833
|
|
|
834
|
+
### Refusals
|
|
835
|
+
|
|
836
|
+
A handler that refuses a request says why, in words for the user; see
|
|
837
|
+
[Refusing a request](./page-files.md#refusing-a-request). The hub shows
|
|
838
|
+
them where they belong:
|
|
839
|
+
|
|
840
|
+
- A message for the request as a whole is the value of the
|
|
841
|
+
`lb-request-refused` stamp on the element that committed, empty when the
|
|
842
|
+
refusal has none.
|
|
843
|
+
- A message for a column goes on the control the request gathered it from,
|
|
844
|
+
as HTML's own validity: `setCustomValidity`, the `:invalid` pseudo-class,
|
|
845
|
+
and the browser's own bubble for the first, which takes focus.
|
|
846
|
+
|
|
847
|
+
A stylesheet shows the whole-request message with no script:
|
|
848
|
+
|
|
849
|
+
```css
|
|
850
|
+
form[lb-request-refused]:not([lb-request-refused=""])::after {
|
|
851
|
+
content: attr(lb-request-refused);
|
|
852
|
+
color: firebrick;
|
|
853
|
+
}
|
|
854
|
+
input:invalid {
|
|
855
|
+
outline: 2px solid firebrick;
|
|
856
|
+
}
|
|
857
|
+
```
|
|
858
|
+
|
|
859
|
+
A refusal is not a failure: `lb-request-error` is not stamped, and nothing
|
|
860
|
+
is reported to the console.
|
|
861
|
+
|
|
862
|
+
A refusal stands until the user edits any control the request gathered,
|
|
863
|
+
resets its form, or sends from the same element again. Then every message
|
|
864
|
+
it put up goes at once, since the next submit is a new question for the
|
|
865
|
+
handler. While a control carries a message the browser holds its form's
|
|
866
|
+
submit, as for any invalid control, so the user edits before trying again.
|
|
867
|
+
|
|
868
|
+
A form-associated custom element takes a column's message when it has
|
|
869
|
+
`setCustomValidity` and `reportValidity`; see
|
|
870
|
+
[Being a control](./custom-elements.md#being-a-control).
|
|
871
|
+
|
|
488
872
|
### The request event
|
|
489
873
|
|
|
490
874
|
The hub dispatches every request as a bubbling `lb-request` event from the
|
|
@@ -531,3 +915,7 @@ expansion, and refuses to build:
|
|
|
531
915
|
- `lb-show` on a `<template>`, or on a row template's root
|
|
532
916
|
- `lb-show` with no `lb-query` around it
|
|
533
917
|
- `lb-show="!"` or `lb-show="!!column"`, which reverse no column
|
|
918
|
+
- `lb-select` on anything but `<input type="checkbox">`, outside a row
|
|
919
|
+
template, or beside `lb-column` or `lb-request`
|
|
920
|
+
- a `command` beginning `--lb-` that is not one of the three commands
|
|
921
|
+
- one of the three commands with no `commandfor`
|