@loadbare/app 0.8.1 → 0.9.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/core/lb-constants.d.ts +3 -0
- package/dist/core/lb-constants.d.ts.map +1 -1
- package/dist/core/lb-constants.js +28 -4
- package/dist/core/lb-constants.js.map +1 -1
- package/dist/core/lb-types.d.ts +11 -0
- package/dist/core/lb-types.d.ts.map +1 -1
- package/dist/core/lb-types.js +20 -0
- package/dist/core/lb-types.js.map +1 -1
- package/dist/hub/lb-apply.d.ts +10 -0
- package/dist/hub/lb-apply.d.ts.map +1 -1
- package/dist/hub/lb-apply.js +15 -1
- 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 +161 -38
- package/dist/hub/lb-hub.browser.js.map +1 -1
- package/dist/server/lb-express.d.ts +22 -7
- package/dist/server/lb-express.d.ts.map +1 -1
- package/dist/server/lb-express.js +79 -31
- package/dist/server/lb-express.js.map +1 -1
- package/dist/server/lb-server.d.ts +26 -0
- package/dist/server/lb-server.d.ts.map +1 -1
- package/dist/server/lb-server.js +53 -3
- package/dist/server/lb-server.js.map +1 -1
- package/docs/TECHREF-1.0.md +154 -22
- package/docs/comparison.md +8 -7
- package/docs/reference/chrome.md +5 -3
- package/docs/reference/data-binding.md +33 -0
- package/docs/reference/page-files.md +39 -0
- package/docs/reference/server.md +17 -0
- package/docs/reference/widgets.md +6 -2
- package/docs/roadmap.md +28 -0
- package/docs/theory.md +8 -1
- package/docs/tutorials/010-pages-and-navigation.md +2 -1
- package/package.json +1 -1
- package/skills/loadbare-app/SKILL.md +36 -8
- package/skills/loadbare-app/references/TECHREF-1.0.md +154 -22
- package/skills/loadbare-app/references/chrome.md +5 -3
- package/skills/loadbare-app/references/data-binding.md +33 -0
- package/skills/loadbare-app/references/page-files.md +39 -0
- package/skills/loadbare-app/references/server.md +17 -0
- package/skills/loadbare-app/references/widgets.md +6 -2
|
@@ -106,14 +106,6 @@ in the row.
|
|
|
106
106
|
stays a flag, since it is what locates the file. State the precedence
|
|
107
107
|
between a flag and a key once. Its key names join the permanent surface,
|
|
108
108
|
so this lands before 1.0 or not at all.
|
|
109
|
-
- **Decide whether a URL carries view parameters.** A URL names a page and
|
|
110
|
-
nothing finer — see [What a URL names](#what-a-url-names) — and a query
|
|
111
|
-
takes no argument from the browser. So a page has nowhere to keep which
|
|
112
|
-
record it shows, a filter, a sort, or a collapsed section: a reload or a
|
|
113
|
-
shared link loses them, and a filter is lost whenever an action re-runs its
|
|
114
|
-
query. Parameters on a page URL, as `<form method="get">` puts its fields
|
|
115
|
-
in the query string, are one answer. Deciding against them, and leaving
|
|
116
|
-
view state to the application, is another. Write whichever one down.
|
|
117
109
|
- **Decide CSS pairing.** Naming a stylesheet `<tag>.css` beside its
|
|
118
110
|
definition would let the builder ship only what survives expansion.
|
|
119
111
|
Recommend deferring the mechanism and reserving the configuration key, so
|
|
@@ -507,8 +499,11 @@ A list nested in another list's rows receives the same rows in every outer
|
|
|
507
499
|
row. That serves a picker offering the same choices on every row, and is
|
|
508
500
|
not a way to show a different detail per row.
|
|
509
501
|
|
|
510
|
-
Which master a page shows is
|
|
511
|
-
|
|
502
|
+
Which master a page shows is a query parm, which a query reads off `ctx`
|
|
503
|
+
since it takes no argument from the browser — see [Query parms](#query-parms).
|
|
504
|
+
When a write creates or removes the master, the server response changes that
|
|
505
|
+
parm — see
|
|
506
|
+
[When a server response changes the query parms](#when-a-server-response-changes-the-query-parms).
|
|
512
507
|
|
|
513
508
|
### Requests
|
|
514
509
|
|
|
@@ -638,15 +633,16 @@ A failed insert resets nothing, so the entry can be corrected.
|
|
|
638
633
|
|
|
639
634
|
A navigation that fails to load its data sets nothing. No element
|
|
640
635
|
dispatched it, so there is nothing to stamp, and the hub reports it to the
|
|
641
|
-
console.
|
|
636
|
+
console. A load started by a control writing a query parm stamps that
|
|
637
|
+
control, as a request stamps its origin.
|
|
642
638
|
|
|
643
639
|
### Links
|
|
644
640
|
|
|
645
641
|
---- UNEDITED ----
|
|
646
642
|
|
|
647
643
|
An anchor carrying `lb-nav-link` navigates inside the application: the hub
|
|
648
|
-
catches the click, pushes the anchor's path onto history,
|
|
649
|
-
host in `<main>`. An anchor without it is left alone and behaves like any
|
|
644
|
+
catches the click, pushes the anchor's path and query string onto history,
|
|
645
|
+
and swaps the page host in `<main>`. An anchor without it is left alone and behaves like any
|
|
650
646
|
other link, so leaving the application is the default and staying in it is
|
|
651
647
|
the opt-in.
|
|
652
648
|
|
|
@@ -660,6 +656,11 @@ link to determine the path.
|
|
|
660
656
|
Path space is flat. A path such as `/members` links to the `members.*` files
|
|
661
657
|
on the server.
|
|
662
658
|
|
|
659
|
+
The query string is kept. `/transactions?date_begin=2026-09-01` opens the
|
|
660
|
+
transactions page narrowed to those dates, and a link to the page it is
|
|
661
|
+
already on loads that page again at the new URL without replacing its DOM —
|
|
662
|
+
see [Query parms](#query-parms).
|
|
663
|
+
|
|
663
664
|
The bare path `/` resolves to `index`.
|
|
664
665
|
|
|
665
666
|
A path that names no page is detected in the browser, after a successful
|
|
@@ -680,19 +681,122 @@ See also [Navigation Row lb-navigation](#lb-navigation).
|
|
|
680
681
|
|
|
681
682
|
#### What a URL names
|
|
682
683
|
|
|
683
|
-
|
|
684
|
-
and Loadbare/app does not reproduce REST: `/accounts/42` is not a
|
|
685
|
-
reach account 42.
|
|
684
|
+
The path names a page, a place in the application. It never names a
|
|
685
|
+
resource, and Loadbare/app does not reproduce REST: `/accounts/42` is not a
|
|
686
|
+
way to reach account 42.
|
|
687
|
+
|
|
688
|
+
The query string describes what that page has on screen:
|
|
689
|
+
`/accounts?acct=23&from=2026-09-09`. It never commands, and the server
|
|
690
|
+
remembers nothing, so a URL is a reproducible view. Reload it, bookmark it,
|
|
691
|
+
or mail it to someone, and what they see is what the sender saw.
|
|
686
692
|
|
|
687
693
|
A page declares what it shows, its queries, and what it allows, its actions.
|
|
688
694
|
Loading a page runs its queries. A request performs an action at a position.
|
|
689
695
|
A row is addressed by `list` and `key`, taken from where the element sits,
|
|
690
696
|
which is how the database already names it. Nothing is fetched by URL, so an
|
|
691
|
-
application designs no endpoints
|
|
692
|
-
|
|
697
|
+
application designs no endpoints.
|
|
698
|
+
|
|
699
|
+
That last is where query parms move Loadbare's position. A query still takes
|
|
700
|
+
no argument from the browser, and a parm arrives the way the session cookie
|
|
701
|
+
does, as part of the request the context is built from. But a user who
|
|
702
|
+
types `?acct=99999` now influences what a query returns. A query parm is
|
|
703
|
+
user input, validated like any other where the application reads it, and a
|
|
704
|
+
per-session database role means an id outside the caller's reach finds
|
|
705
|
+
nothing.
|
|
706
|
+
|
|
707
|
+
Loadbare is for applications, not sites. Every route is answered with the
|
|
708
|
+
same document, and a path that names no page is found out in the browser —
|
|
709
|
+
see [Links](#links).
|
|
710
|
+
|
|
711
|
+
#### Query parms
|
|
712
|
+
|
|
713
|
+
A control that narrows what a page shows writes its value into the query
|
|
714
|
+
string, rather than sending it:
|
|
715
|
+
|
|
716
|
+
```html
|
|
717
|
+
<lb-options lb-list="teams" lb-query-parm="team" exp-label="Team:">
|
|
718
|
+
<option value="">Every team</option>
|
|
719
|
+
<template lb-key="id"><option lb-cell="name"></option></template>
|
|
720
|
+
</lb-options>
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
| Attribute | Written by | Behavior |
|
|
724
|
+
| -------------------- | ---------- | --------------------------------------------------------------- |
|
|
725
|
+
| `lb-query-parm` | Developer | On a control: its `change` writes this parm and reloads the page |
|
|
726
|
+
| `lb-query-parm-push` | Developer | With `lb-query-parm`: the write pushes a history entry |
|
|
727
|
+
|
|
728
|
+
On `change`, the hub reads the control's value the way a form reads a cell,
|
|
729
|
+
and sets that one parm in the URL. Every other parm is left as it is, since
|
|
730
|
+
it may have arrived by link with no control on screen to say it again. An
|
|
731
|
+
empty value takes the parm out, so a URL is as long as the user has narrowed
|
|
732
|
+
the page. A value the URL already carries does nothing.
|
|
733
|
+
|
|
734
|
+
The write replaces the current history entry: changing what a page shows is
|
|
735
|
+
not going anywhere, so Back leaves the page rather than walking back through
|
|
736
|
+
every choice. `lb-query-parm-push` makes the write push an entry instead.
|
|
737
|
+
|
|
738
|
+
The page then loads at the new URL exactly as a cold load of that URL would:
|
|
739
|
+
`onPageEnter`, then every query. The page's DOM is kept, and the answer
|
|
740
|
+
lands by key, so a list that gets its rows back keeps them and its scroll
|
|
741
|
+
position.
|
|
742
|
+
|
|
743
|
+
After every load — cold, by link, by Back, by a write — the hub lands each
|
|
744
|
+
parm on the control that writes it, and an absent parm lands empty. A
|
|
745
|
+
control therefore shows what the address bar says.
|
|
746
|
+
|
|
747
|
+
A control that writes a query parm sends no request. One that also carries
|
|
748
|
+
`lb-action` has that request refused, since the choice would otherwise be
|
|
749
|
+
sent twice.
|
|
750
|
+
|
|
751
|
+
Every round trip carries the query string the browser is showing, a page
|
|
752
|
+
load and an action alike. The server hands its parms to `contextFor` — see
|
|
753
|
+
[The Express server](#the-express-server). Nothing in Loadbare assigns a
|
|
754
|
+
parm a meaning.
|
|
693
755
|
|
|
694
|
-
|
|
695
|
-
|
|
756
|
+
#### When a server response changes the query parms
|
|
757
|
+
|
|
758
|
+
Some query parms can only be known once a write has run. After an insert,
|
|
759
|
+
the key of the new row exists only on the server. After a delete, only the
|
|
760
|
+
server knows that the row the page was showing is gone.
|
|
761
|
+
|
|
762
|
+
The usual web answer is Post/Redirect/Get: the server answers the write with
|
|
763
|
+
a redirect to a URL naming the result, and the browser makes a second request
|
|
764
|
+
to load it. Loadbare/app does the same work in one round trip, and never
|
|
765
|
+
changes the path.
|
|
766
|
+
|
|
767
|
+
A request's `run` returns `queryParms()`, naming the parms the write decided.
|
|
768
|
+
The server loads the page with those parms set, as a cold load of the
|
|
769
|
+
resulting URL would: `onPageEnter`, then every query. The server response
|
|
770
|
+
carries the parms and that load together. The hub sets the parms in the URL,
|
|
771
|
+
replacing the history entry, and then lands the load.
|
|
772
|
+
|
|
773
|
+
```ts
|
|
774
|
+
rowInsert: {
|
|
775
|
+
run: async (ctx, { values }) => {
|
|
776
|
+
const id = await ctx.db.addAccount(values);
|
|
777
|
+
return queryParms({ acct: String(id) });
|
|
778
|
+
},
|
|
779
|
+
refresh: [],
|
|
780
|
+
},
|
|
781
|
+
```
|
|
782
|
+
|
|
783
|
+
- Only query parms change. A server response cannot send the browser to
|
|
784
|
+
another page.
|
|
785
|
+
- Parms the response does not name are left as they are. An empty value
|
|
786
|
+
removes its parm.
|
|
787
|
+
- At least one parm is named, and every value is a string. Otherwise the
|
|
788
|
+
server warns, ignores the parms, and runs the refresh set as usual.
|
|
789
|
+
- The refresh set does not run, and anything else `run` returned is dropped.
|
|
790
|
+
Both were answers for the query string the page is leaving.
|
|
791
|
+
- If loading the page fails, the write has still happened. The response
|
|
792
|
+
carries the parms alone, and the hub loads the page itself. A failure
|
|
793
|
+
there is a page load's, and is not stamped on the element that sent the
|
|
794
|
+
request.
|
|
795
|
+
- A user who has left the page by the time the response arrives keeps the
|
|
796
|
+
URL they are on.
|
|
797
|
+
|
|
798
|
+
The page is loaded with a second context, built by `contextFor` from the new
|
|
799
|
+
parms — see [The Express server](#the-express-server).
|
|
696
800
|
|
|
697
801
|
### lb-navigation
|
|
698
802
|
|
|
@@ -706,10 +810,11 @@ like a server-produced result.
|
|
|
706
810
|
| Cell | Holds |
|
|
707
811
|
| ------------ | ------------------------------------------------------------------- |
|
|
708
812
|
| `page-label` | The text of the link to the current page, empty if no link names it |
|
|
709
|
-
| `page-uri` | The path as the browser has
|
|
813
|
+
| `page-uri` | The path and query string as the browser has them, such as `/members?team=Engines` |
|
|
710
814
|
|
|
711
815
|
The `page-uri` is taken from the current URL. The `page-label` is taken from the first
|
|
712
|
-
`lb-nav-link` link in the document (presumably in a nav bar)
|
|
816
|
+
`lb-nav-link` link in the document (presumably in a nav bar) whose path matches the
|
|
817
|
+
current path, so the query string does not change it.
|
|
713
818
|
|
|
714
819
|
The row lands before the page is looked up, so a path that names no page has
|
|
715
820
|
it too, and an `lb-unknown-page` dialog, where the chrome has one, displays
|
|
@@ -871,6 +976,24 @@ Explaining Express is beyond the scope of this technical reference. The
|
|
|
871
976
|
only real requirement is that the catch-all for app.html is at the end,
|
|
872
977
|
so it does not catch any other files.
|
|
873
978
|
|
|
979
|
+
`hubRoutes` answers `POST /lb/<page>`, with the query string the browser is
|
|
980
|
+
showing after it, verbatim. It hands `contextFor` that query string's parms
|
|
981
|
+
as a second argument, and `contextFor` puts on the context whatever a query
|
|
982
|
+
reads from them. They are user input:
|
|
983
|
+
|
|
984
|
+
```ts
|
|
985
|
+
function contextFor(req: Request, parms: URLSearchParams): HubContext {
|
|
986
|
+
return { db: openDb(), acct: parms.get("acct") ?? "" };
|
|
987
|
+
}
|
|
988
|
+
```
|
|
989
|
+
|
|
990
|
+
Read the parms from that argument, not from `req.query`. After a request
|
|
991
|
+
whose `run` returned `queryParms()`, `contextFor` is called a second time for
|
|
992
|
+
the same request, with the new parms, to load the page at them. So it must
|
|
993
|
+
be safe to call twice, and a write must be visible to the second context by
|
|
994
|
+
the time its `run` returns. A handle opened per request without a
|
|
995
|
+
transaction around it is both.
|
|
996
|
+
|
|
874
997
|
Give the server the origin root. The hub reaches its own endpoints by
|
|
875
998
|
absolute path, so an application cannot be hosted under a subpath such as
|
|
876
999
|
`example.com/myapp/`, and anything proxying in front of the server passes
|
|
@@ -941,6 +1064,13 @@ interaction happened, as `list`, `row`, `key`, `cell` and `value`. Under
|
|
|
941
1064
|
ones. That is how a delta reaches the browser: wrap it in `patch()`, naming
|
|
942
1065
|
the rows that arrived or changed and the keys that went.
|
|
943
1066
|
|
|
1067
|
+
`run` may instead return `queryParms()`, naming query parms only the write
|
|
1068
|
+
can know, such as the key of a row it inserted. The page then loads at them
|
|
1069
|
+
in the same round trip, in place of the refresh set — see
|
|
1070
|
+
[When a server response changes the query parms](#when-a-server-response-changes-the-query-parms).
|
|
1071
|
+
A `rowDelete` that removes the row on screen returns `queryParms({ acct: "" })`
|
|
1072
|
+
and leaves any other delete to its refresh set.
|
|
1073
|
+
|
|
944
1074
|
```ts
|
|
945
1075
|
// members.requests.ts
|
|
946
1076
|
import { patch, type Requests } from "@loadbare/app/server";
|
|
@@ -1148,6 +1278,8 @@ Each attribute is defined in one section, and this table says which.
|
|
|
1148
1278
|
| `lb-value` | Hub | [How a value lands](#how-a-value-lands) |
|
|
1149
1279
|
| `lb-action` | Developer | [Requests](#requests) |
|
|
1150
1280
|
| `lb-nav-link` | Developer | [Links](#links) |
|
|
1281
|
+
| `lb-query-parm` | Developer | [Query parms](#query-parms) |
|
|
1282
|
+
| `lb-query-parm-push` | Developer | [Query parms](#query-parms) |
|
|
1151
1283
|
| `lb-pending` | Hub | [Request state](#request-state) |
|
|
1152
1284
|
| `lb-error` | Hub | [Request state](#request-state) |
|
|
1153
1285
|
| `lb-row-count` | Hub | [Request state](#request-state) |
|
|
@@ -73,7 +73,9 @@ sits directly inside `<body>`, with banner, nav, footer and `<main>` inside
|
|
|
73
73
|
it, so Loadbare can act on all of them.
|
|
74
74
|
|
|
75
75
|
A navigation anchor's `href` is a path, and the path names a page:
|
|
76
|
-
`/members` shows `members.page.html`. A
|
|
76
|
+
`/members` shows `members.page.html`. A query string on it is kept, so
|
|
77
|
+
`/members?team=Engines` opens the page narrowed; see
|
|
78
|
+
[Query parms](./data-binding.md#query-parms). A bare `/` resolves to `index`, so the
|
|
77
79
|
landing page is the one named `index.page.html`. An anchor without
|
|
78
80
|
`lb-nav-link` is left alone and behaves like any other link.
|
|
79
81
|
|
|
@@ -100,10 +102,10 @@ shows a value — so a chrome displays the current page with no code at all:
|
|
|
100
102
|
| Cell | Holds |
|
|
101
103
|
|--------------|-----------------------------------------------------------|
|
|
102
104
|
| `page-label` | The text of the `lb-nav-link` anchor for the path, or empty if none |
|
|
103
|
-
| `page-uri` | The path as the browser has
|
|
105
|
+
| `page-uri` | The path and query string as the browser has them, such as `/members?team=Engines` |
|
|
104
106
|
|
|
105
107
|
The label is the nav's. The hub takes it from the first `lb-nav-link`
|
|
106
|
-
anchor whose
|
|
108
|
+
anchor whose path names the current page, whatever its query string, so a click, a reload and the
|
|
107
109
|
back button all land the same text, and a path no anchor names lands an
|
|
108
110
|
empty label. A chrome that shows the label somewhere fixed should expect
|
|
109
111
|
that case for a page reachable only by URL.
|
|
@@ -304,6 +304,39 @@ Leave `lb-action` off a widget inside an `lb-row-insert` or `lb-row-update`
|
|
|
304
304
|
form. The form reads every `lb-cell` in it on submit, so a widget that also
|
|
305
305
|
sent its own would write the same edit twice.
|
|
306
306
|
|
|
307
|
+
## Query parms
|
|
308
|
+
|
|
309
|
+
A control that narrows what the page shows writes its value into the query
|
|
310
|
+
string instead of sending a request. `lb-query-parm` names the parm:
|
|
311
|
+
|
|
312
|
+
```html
|
|
313
|
+
<select lb-query-parm="team">
|
|
314
|
+
<option value="">Every team</option>
|
|
315
|
+
<option value="Engines">Engines</option>
|
|
316
|
+
</select>
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
On `change` the hub sets that one parm in the URL, leaving every other parm
|
|
320
|
+
alone, and takes it out when the value is empty. The write replaces the
|
|
321
|
+
current history entry; add `lb-query-parm-push` to push one instead. The page
|
|
322
|
+
then loads at the new URL, exactly as a cold load of it would, without
|
|
323
|
+
replacing its DOM.
|
|
324
|
+
|
|
325
|
+
After every load the hub lands each parm on the control that writes it, and
|
|
326
|
+
an absent parm lands empty, so the control shows what the address bar says.
|
|
327
|
+
|
|
328
|
+
A control that writes a query parm sends no request, and one that also
|
|
329
|
+
carries `lb-action` has that request refused.
|
|
330
|
+
|
|
331
|
+
A request can write parms too, when only the write knows their value, such as
|
|
332
|
+
the key of a row it inserted; see
|
|
333
|
+
[refresh and patch](./page-files.md#refresh-and-patch). The page loads at
|
|
334
|
+
them in the same round trip, and they land on their controls as above.
|
|
335
|
+
|
|
336
|
+
The server hands the parms to `contextFor`; see
|
|
337
|
+
[the Express server](./server.md#database-layer). See
|
|
338
|
+
[Query parms](./TECHREF-1.0.md#query-parms) for the whole rule.
|
|
339
|
+
|
|
307
340
|
## Conditional rendering
|
|
308
341
|
|
|
309
342
|
Loadbare ships static HTML and hydrates elements that are already in the
|
|
@@ -192,3 +192,42 @@ resetRoster: {
|
|
|
192
192
|
refresh: ["roster"],
|
|
193
193
|
},
|
|
194
194
|
```
|
|
195
|
+
|
|
196
|
+
Return `queryParms()` instead when the server response changes the query
|
|
197
|
+
parms: after an insert, only the server knows the new key, and after a delete,
|
|
198
|
+
only the server knows the parm should go. The page loads at the query string
|
|
199
|
+
with those parms set, in the same round trip, and the hub writes them into the
|
|
200
|
+
URL, replacing the history entry. This is Post/Redirect/Get without the
|
|
201
|
+
redirect. The refresh set does not run, and nothing else `run` returned is
|
|
202
|
+
sent, since both answered for the query string the page left. Name at least
|
|
203
|
+
one parm, give each a string, and use an empty string to take one out:
|
|
204
|
+
|
|
205
|
+
```ts
|
|
206
|
+
// src/pages/accounts.requests.ts
|
|
207
|
+
import { queryParms, type Requests } from "@loadbare/app/server";
|
|
208
|
+
|
|
209
|
+
export const requests: Requests = {
|
|
210
|
+
crud: {
|
|
211
|
+
accounts: {
|
|
212
|
+
rowInsert: {
|
|
213
|
+
run: async (ctx, { values }) => {
|
|
214
|
+
const id = await ctx.db.addAccount(values);
|
|
215
|
+
return queryParms({ acct: String(id) });
|
|
216
|
+
},
|
|
217
|
+
refresh: [],
|
|
218
|
+
},
|
|
219
|
+
rowDelete: {
|
|
220
|
+
run: async (ctx, { key }) => {
|
|
221
|
+
await ctx.db.deleteAccount(key);
|
|
222
|
+
if (key === ctx.acct) return queryParms({ acct: "" });
|
|
223
|
+
},
|
|
224
|
+
refresh: ["accounts"],
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
};
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Only parms: `run` cannot send the browser to another page. The loaded page
|
|
232
|
+
reads the new parms through `contextFor` like any others; see
|
|
233
|
+
[the Express server](./server.md#database-layer).
|
|
@@ -137,6 +137,23 @@ declare module "@loadbare/app/server" {
|
|
|
137
137
|
}
|
|
138
138
|
```
|
|
139
139
|
|
|
140
|
+
The query string the browser is showing arrives on every data request, and
|
|
141
|
+
`contextFor` gets its parms as a second argument. Put on the context whatever
|
|
142
|
+
a query reads from them, and treat them as user input:
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
function contextFor(req: Request, parms: URLSearchParams): HubContext {
|
|
146
|
+
return { db: openDb(), team: parms.get("team") ?? "" };
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Read the parms from that argument, not from `req.query`. When a server
|
|
151
|
+
response changes the query parms, `contextFor` is called a second time for
|
|
152
|
+
that request, with the new parms, to load the page at them; see [refresh and patch](./page-files.md#refresh-and-patch). Write it to
|
|
153
|
+
be safe to call twice, and make a write visible to the second context by the
|
|
154
|
+
time `run` returns: a handle opened per request, with no transaction held
|
|
155
|
+
open across the two, is both.
|
|
156
|
+
|
|
140
157
|
Add a field for anything else a request needs — the authenticated user, a
|
|
141
158
|
request id, a feature flag set. Queries and requests read them from `ctx`; see
|
|
142
159
|
[page files](./page-files.md).
|
|
@@ -56,7 +56,8 @@ action carries a value.
|
|
|
56
56
|
| ---------- | ----- |
|
|
57
57
|
| `exp-label` | the visible `<label>` text |
|
|
58
58
|
|
|
59
|
-
Requires `lb-action` — a change with
|
|
59
|
+
Requires `lb-action` or `lb-query-parm` — a change with neither logs and
|
|
60
|
+
sends nothing. With `lb-query-parm` the hub writes the choice into the URL.
|
|
60
61
|
|
|
61
62
|
## `lb-options`
|
|
62
63
|
|
|
@@ -81,8 +82,11 @@ hand. The author supplies the row template inside the widget (via
|
|
|
81
82
|
once, with `lb-key`.
|
|
82
83
|
- `data-group` on the row template sections the options into `<optgroup>`s,
|
|
83
84
|
one per distinct value, created and removed as rows arrive and leave.
|
|
85
|
+
- `lb-value` selects the option with that key, including one that arrives
|
|
86
|
+
after the value did.
|
|
84
87
|
- A `change` sends the action named by `lb-action`, value from the
|
|
85
|
-
select's `.value`.
|
|
88
|
+
select's `.value`. With `lb-query-parm` instead, the hub writes the
|
|
89
|
+
choice into the URL.
|
|
86
90
|
|
|
87
91
|
`lb-picker` is this same class with its row template supplied by the
|
|
88
92
|
definition instead of the page — see below.
|