Frontend: Load or Create - that is the Question
You almost made it. In this chapter we write our component to either load or create a list. The idea:
- We get a uuid by input or we get a uuid by creating a new list in the backend
- We then route to our main
Home
component to with alist_uuid
.
Add a dynamic route
In order to route dynamically to our main Home
component two things have to be done.
- We need a dynamic route, something like
/list/<uuid>
. - This
<uuid
> parameter then has the be given to ourHome
component.
Let's start with our Home
component. Add a list_uuid
component property.
#![allow(unused)] fn main() { #[component] pub fn Home(list_uuid: String) -> Element { let list_uuid = use_signal(|| list_uuid); let change_signal = use_signal(|| ListChanged); rsx! { ShoppingList{list_uuid, change_signal} ItemInput{list_uuid, change_signal} } } }
And you might have noticed - we removed our hardcoded uuid :).
Then we also need to have a dynamic route. Go to our Route
enum (in our frontend).
#![allow(unused)] fn main() { #[derive(Routable, Clone)] pub enum Route { #[layout(Layout)] #[route("/list/:list_uuid")] Home { list_uuid: String }, #[route("/profile")] Profile {}, } }
Great! with this we are now dynamically routable. Let's create a new component that will route to our new Home
with a list_uuid
.
Create a new list
Let's create a new component, that load or create a new list. You also see the use_navigator
hook. It allows is to route to other pages we have!
#![allow(unused)] fn main() { #[component] pub fn LoadOrCreateList() -> Element { let nav = use_navigator(); let on_create_list_click = move |_| { let nav = nav.clone(); spawn({ async move { let response = create_list().await; if let Ok(created_list) = response { nav.push(Route::Home { list_uuid: created_list.uuid, }); } } }); }; rsx! { div{ class: "grid place-content-evently grid-cols-1 md:grid-cols-2 w-full gap-4", div { class: "card glass min-h-500 flex flex-col content-end gap-4 p-4", button{ class: "btn btn-primary", onclick: on_create_list_click, "Create new List" } } } } } }
Add this new component to the Route
as this is now the first page we see, when we open up our url:
#![allow(unused)] fn main() { #[derive(Routable, Clone)] pub enum Route { #[layout(Layout)] #[route("/")] LoadOrCreateList {}, #[route("/list/:list_uuid")] Home { list_uuid: String }, #[route("/profile")] Profile {}, } }
If you then also route correctly in our Layout
then we have a working routing in our frontend :) We can only create new list's though
#![allow(unused)] fn main() { #[component] pub fn Layout() -> Element { rsx! { div { class: "min-h-screen bg-base-300", div { class: "navbar flex", div { Link { class: "p-4", to: Route::LoadOrCreateList{}, "Home" } Link { class: "p-4", to: Route::Profile{}, "Profile" } } } div { class: "container mx-auto max-w-[1024px] p-8", Outlet::<Route>{} } } } } }
If you now run all the code - you can create a new list with a click of a button - and it will route you to the page with the freshly created list.
Load a list from given Uuid
In this chapter, we create a form. Here the user has to input a given uuid. Then we forward with the given uuid.
Let's expand our LoadOrCreateList
our component! As you already have seen how to create a form - we fast forward.
What we've changed:
- We have a input form where we can input a string.
- That string get copied to our
list_uuid
Signal. - On clicking the
Load existing list
button we read the storedlist_uuid
and route to our Home again with this uuid.
#![allow(unused)] fn main() { #[component] pub fn LoadOrCreateList() -> Element { let nav = use_navigator(); let mut list_uuid = use_signal(|| "".to_string()); let onloadsubmit = move |_| { spawn({ async move { let uuid_value = list_uuid.read().clone(); if !uuid_value.is_empty() { nav.push(Route::Home { list_uuid: uuid_value, }); } } }); }; let on_create_list_click = move |_| { let nav = nav.clone(); spawn({ async move { let response = create_list().await; if let Ok(created_list) = response { nav.push(Route::Home { list_uuid: created_list.uuid, }); } } }); }; rsx! { div{ class: "grid place-content-evently grid-cols-1 md:grid-cols-2 w-full gap-4", div { class: "card glass min-h-500 flex flex-col content-end gap-4 p-4", button{ class: "btn btn-primary", onclick: on_create_list_click, "Create new List" } } div { class: "card glass min-h-500", form { onsubmit: onloadsubmit, div { class: "flex flex-col gap-4 p-4", input{ class:"input input-bordered", r#type:"text", placeholder:"Enter UUID here...", id: "uuid", name: "uuid", oninput: move |e| list_uuid.set(e.data.value()) } button{ class: "btn btn-primary", r#type: "submit", "Load existing List" } } } } } } } }
Nice! You've done it! :) If you want - you can stay for some styling.