Fix form options source query parameters (#1356)

This commit is contained in:
Ophir LOJKINE
2026-07-29 11:37:36 +02:00
committed by GitHub
parent 217702550e
commit a065bb8d0f
4 changed files with 15 additions and 8 deletions
+1
View File
@@ -3,6 +3,7 @@
## unreleased
- `sqlpage.send_mail` now supports rich email bodies. Use `body_html` for a caller-provided HTML alternative, or `body_md` to render Markdown as HTML. Messages retain a plain-text alternative; `body` may be omitted when `body_md` is used, and `body_md` and `body_html` cannot be combined.
- Form `options_source` URLs now preserve existing query parameters when adding the dynamic `search` parameter.
## v0.45
@@ -442,6 +442,8 @@ We''ll write a second SQL file, `options_source.sql`, that will receive the user
When both `options` and `options_source` are set, the local `options` are loaded first. Search results from `options_source` are loaded into the same option list; a result with the same `value` updates the existing option. This is useful to set a default preselected value with `options_source`.
`options_source` may already contain query parameters. SQLPage preserves them and adds or replaces the `search` parameter when loading options.
##### `options_source.sql`
```sql
@@ -458,7 +460,7 @@ where label like $search || ''%'';
{"name": "component", "type": "select",
"value": "form",
"options": [{"label": "Form", "value": "form"}],
"options_source": "examples/from_component_options_source.sql",
"options_source": "examples/from_component_options_source.sql?category=component",
"description": "Start typing the name of a component like ''map'' or ''form''..."
}]')),
('form', 'This example illustrates the use of the `radio` type.
+3 -3
View File
@@ -53,9 +53,9 @@ function sqlpage_load_options_source(options_source) {
if (!options_source) return;
return async (query, callback) => {
const err = (label) => callback([{ label, value: "" }]);
const resp = await fetch(
`${options_source}?search=${encodeURIComponent(query)}`,
);
const options_url = new URL(options_source, document.baseURI);
options_url.searchParams.set("search", query);
const resp = await fetch(options_url);
if (!resp.ok) {
return err(
`Error loading options from "${options_source}": ${resp.status} ${resp.statusText}`,
+8 -4
View File
@@ -213,14 +213,14 @@ test("form select combines initial options with remote search results", async ({
const select = page
.locator(
'select[data-options_source="examples/from_component_options_source.sql"]',
'select[data-options_source="examples/from_component_options_source.sql?category=component"]',
)
.first();
await expect(select).toBeAttached();
await page.waitForFunction(
() =>
!!document.querySelector<HTMLSelectElement>(
'select[data-options_source="examples/from_component_options_source.sql"]',
'select[data-options_source="examples/from_component_options_source.sql?category=component"]',
)?.tomselect,
);
@@ -246,7 +246,9 @@ test("form select combines initial options with remote search results", async ({
await page.waitForResponse((response) =>
response
.url()
.includes("examples/from_component_options_source.sql?search=form"),
.includes(
"examples/from_component_options_source.sql?category=component&search=form",
),
);
await expect
.poll(async () =>
@@ -265,7 +267,9 @@ test("form select combines initial options with remote search results", async ({
await page.waitForResponse((response) =>
response
.url()
.includes("examples/from_component_options_source.sql?search=map"),
.includes(
"examples/from_component_options_source.sql?category=component&search=map",
),
);
await expect
.poll(async () =>