SearchPanel

SearchPanel from vertigo-forms is an input with results loaded for the typed query. It takes:

  • query - a Value with the typed text,
  • cache - an AutoMap giving a resource for every query, usually a LazyCache,
  • render_results - a function rendering the loaded results,
  • params - texts and the minimal number of characters needed to start searching.
    use std::rc::Rc;
    use vertigo::{dom, AutoJsJson, AutoMap, DomNode, RequestBuilder, Value};
    use vertigo_forms::{SearchPanel, SearchPanelParams};

    #[derive(AutoJsJson, Clone, PartialEq)]
    pub struct City {
        name: String,
        country: String,
    }

    let query = Value::new(String::new());

    // A cached request for every query
    let cache = AutoMap::new(|_, query: &String| {
        RequestBuilder::get(format!("/api/cities?q={query}"))
            .ttl_minutes(10)
            .lazy_cache(|status, body| {
                if status == 200 {
                    Some(body.into::<Vec<City>>())
                } else {
                    None
                }
            })
    });

    let render_results: Rc<dyn Fn(Rc<Vec<City>>) -> DomNode> = Rc::new(|cities| {
        dom! {
            <ul>
                {..cities.iter().map(|city| dom! { <li>{&city.name} ", " {&city.country}</li> })}
            </ul>
        }
    });

    dom! {
        <SearchPanel
            query={query}
            cache={cache}
            render_results={render_results}
            params={SearchPanelParams {
                prompt: "City: ".to_string(),
                min_chars: 2,
                ..Default::default()
            }}
            i:placeholder="Type a city name"
        />
    }

Until enough characters are typed, the panel shows a hint, then a loading text, and finally the results or the "No results" text. As the AutoMap keeps every query, going back to a previous query shows its results instantly, without a request (until the cache expires).

Remember to encode the query if it can contain characters with a special meaning in URLs, like & or #.

The look can be adjusted with attribute groups: c: for the container, i: for the input, pc: for the results and ei: for the "No results" element, like the i:placeholder above.

See it in action, along with other components, in the storybook.