Fix form options source query parameters (#1356)
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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}`,
|
||||
|
||||
@@ -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 () =>
|
||||
|
||||
Reference in New Issue
Block a user