Query parameters

Read URL search params from FlowRequest in pages, loaders, and submits.

LIVE

#[load] + query string

Query:

    Single parameter

    pub fn page(req: FlowRequest) -> View {
        let q = req.query_param("q").unwrap_or("");
        view! {
            <>
                <h1>"Search"</h1>
                <p>"Query: " {q.to_string()}</p>
            </>
        }
    }

    In loaders

    #[load]
    async fn search_results(req: &FlowRequest) -> Result<Vec<Item>, LoaderError> {
        let q = req.query_param("q").unwrap_or("");
        if q.is_empty() {
            return Ok(vec![]);
        }
        db::search(q).await.map_err(|_| LoaderError::new(500, "search failed"))
    }

    Forms that preserve query state

    <form method="get" action="/docs/search">
        <input type="search" name="q" placeholder="Search docs…" />
    </form>

    Reload loaders without full page refresh (SPA)

    Changing only client state does not re-run #[load]. For booking flows (pick a date, refresh time slots), navigate to the same path with new query params so the server renders again:

    on:change={js! {
        const input = event.target;
        if (!(input instanceof HTMLInputElement) || !input.value) return;
        await __resuma.navigate(__resuma.buildUrl("/reservar", {
            fecha: input.value,
            servicio: new URLSearchParams(location.search).get("servicio"),
        }));
    }}

    Use event.target, not event.currentTarget. In async handlers, currentTarget is often null.

    Rust helpers

    loader_refresh_input(
        "/reservar",
        "fecha",
        &date,
        &["servicio"],   // query keys to preserve
        "date",
        vec![("required".into(), AttrValue::Bool(true))],
    )
    
    query_nav_link("/servicios", &[("cat", "corte")], "active", "", vec![...]);
    
    build_query_href("/book", &[("fecha", "2026-06-02")]);

    See template flow-booking (resuma new my-app --template flow-booking) and PWA and public/ for a full sample.

    Flash after redirect

    Combine PRG redirects with a query flag:

    #[submit]
    async fn create(form: ItemForm, _req: &FlowRequest) -> Result<Redirect, SubmitError> {
        db::insert(&form).await.map_err(|_| SubmitError::new("Failed"))?;
        Ok(redirect("/items?created=1"))
    }
    
    pub fn page(req: FlowRequest) -> View {
        let created = req.query_param("created") == Some("1");
        view! {
            <>
                {if created {
                    view! { <p class="toast">"Item created!"</p> }
                } else {
                    View::empty()
                }}
            </>
        }
    }

    Parsing notes

    • Values are percent-decoded by the Flow request layer.
    • Duplicate keys: last value wins (same as typical query parsers).
    • Use path params (req.param('id')) for /users/:id segments.