Query Recipes
Load when a dialog opens
Create the query with the component and read it inside the dialog's {#if open}: the request starts when the dialog opens and stops when it closes.
Markdown version of this page, for assistants (Markdown for AI)
On this page
Example
Open a dialog, close it with Escape before the answer arrives, open it again.
The example runs in the browser.
Requests the server received
- None yet.
Code
<!-- src/lib/members/MemberDialog.svelte -->
<script lang="ts">
import { createQuery } from '@svelte-lean/query';
import { getMember } from '$api/members';
let { id, name }: { id: number; name: string } = $props();
const uid = $props.id();
let dialog = $state<HTMLDialogElement>();
let open = $state(false);
// Created now, requested only when `member` is read on screen.
const member = createQuery(getMember, () => ({ id }));
function show() {
open = true;
dialog?.showModal();
}
</script>
<button type="button" onclick={show}>Details of {name}</button>
<dialog bind:this={dialog} onclose={() => (open = false)} aria-labelledby="{uid}-title">
<h2 id="{uid}-title">{name}</h2>
{#if open}
{#if member.loading}
<p>Loading…</p>
{:else if member.error}
<p role="alert">{member.error.message}</p>
{:else if member.data}
<p>{member.data.email} · {member.data.team} · {member.data.status}</p>
{/if}
{/if}
<form method="dialog"><button>Close</button></form>
</dialog>src/lib/api/members.ts
export const getMember = defineQuery({
get: 'api/members/{id}',
result: type<Member>(),
entity: 'Member',
access: 'members.view'
});How it works
| Moment | Request | State |
|---|---|---|
| The component mounts | none: createQuery creates no entry until it is read | info.status: 'idle' |
| The dialog opens | GET api/members/1, cause mount | loading |
| Closed before the answer | aborted; nothing is written | unchanged |
| Opened again, data cached | none while fresh, else a background refetch | data at once, then refreshing |
Closed for longer than keep | the entry is collected; the next opening fetches | loading |
- The native
<dialog>gives the modal, the focus trap, Escape and the return of focus; the component only tracksopenfrom itscloseevent. $props.id()gives each instance its own heading id foraria-labelledby.
Variations
Read outside the block
When the template reads the query outside {#if open} (a title, a count), when pauses it instead. Its data is kept while paused.
TypeScript
// Read outside {#if}: `when` pauses the query while the dialog is closed and keeps its data.
const member = createQuery(getMember, () => ({ id }), { when: () => open });Prepare before the click
getMember.prefetch({ id }) on pointerenter fills the entry at low priority,
so the dialog opens with data.
Related
- Reading: states,
when, a missing input andload(). - Dependent queries
- Dialog primitive