Query Recipes
Search button
A query that runs when the form is submitted, not on every keystroke. After the first search it is an ordinary query: cached, refetched, polled.
Markdown version of this page, for assistants (Markdown for AI)
On this page
Example
Search for a name, then search for another one and watch the previous results stay.
The example runs in the browser.
Requests the server received
- None yet.
Code
<!-- src/routes/members/search/+page.svelte -->
<script lang="ts">
import { createQuery } from '@svelte-lean/query';
import { listMembers } from '$api/members';
// Nothing is requested until load(); afterwards it shows that search (cached, refetch).
const results = createQuery(listMembers, { when: false, keepPrevious: true });
let term = $state('');
let searched = $state(false);
function submit(event: SubmitEvent) {
event.preventDefault();
// load() resolves with the data; a failure is also written to results.error.
searched = true;
results.load({ search: term }).catch(() => {});
}
</script>
<form role="search" aria-label="Search members" onsubmit={submit}>
<input type="search" aria-label="Name" bind:value={term} />
<button disabled={results.loading}>Search</button>
</form>
{#if !searched}
<p>Enter a name and press Search.</p>
{:else if results.error}
<p role="alert">{results.error.message}</p>
{:else if results.data}
<p>{results.data.total} found{results.info.placeholder ? ', updating' : ''}</p>
<ul>
{#each results.data.rows as member (member.id)}
<li>{member.name}</li>
{/each}
</ul>
{/if}How it works
| Moment | Request | State |
|---|---|---|
| Before the first submit | none | blocked: 'when' |
| Typing | none: the params come from load(), not from state | unchanged |
| Submit | GET api/members?search=…, cause user | loading |
| Submit another term | a new key; the previous request is aborted | loading, previous rows shown, info.placeholder: true |
| Submit a term searched before | a refetch of the cached key | cached rows at once |
{ when: false }pauses automatic fetching;load(params)pins the params and fetches, always with a request.- A native
<form role="search">gives Enter to submit and a search landmark. load()resolves with the data and rejects on failure; the same error is inresults.errorfor the template.
Variations
Run the last search again
TypeScript
// Run the last search again (cause `user`: it shows `loading`).
const again = () => results.refetch();Follow invalidations after the first search
TypeScript
// A search that should also follow invalidations after its first start holds its params in
// state and returns undefined until they exist.
let submitted = $state<string | undefined>();
const live = createQuery(listMembers, () =>
submitted === undefined ? undefined : { search: submitted }
);
const clear = () => {
term = '';
submitted = undefined; // back to "nothing searched yet"; the cache keeps the results
};Related
- Reading:
load()next towhenand a missing input. - Filtered table: filters that apply as you type.