-
|
Apologies if this is a silly question, but I'm still a newbie to Sycamore and Rust. I'm trying to use sycamore routers to pass down a url as a props into my navbar, e.g. I can achieve this using the builder API by doing a bunch of clones and moves of the string, but I have no idea how to achieve this using the Appreciate the hard work in building the library so far! Problematic code using the view!#[component]
fn NavBarEndMenuDsl<'navbar, G: Html>(cx: Scope<'navbar>, props: NavBarProps<'navbar>) -> View<G> {
let subapp = props.subapp;
let login_url = format!("/public/{}/trigger_login", &subapp);
let logout_url = format!("/api/{}/trigger_logout", &subapp);
view! {
cx,
div(class="navbar-end"){
(
if *props.is_logged_in.get() {
view! {cx,
div(class="navbar-item has-dropdown is-hoverable"){
a(class="navbar-link", href="#"){
"User:" (*props.username.get())
}
div(class="navbar-dropdown"){
// having trouble passing it in here into href ---------------
// |
// |
a(class="navbar-item", href=logout_url.clone(), rel="external"){
"Logout"
}
}
}
}
} else {
view! {cx,
a(class="button is-black", href="/public/trigger_login", rel="external"){"Login"}
}
})
}
}
}
#[derive(Prop, Clone)]
pub struct NavBarProps<'navbar> {
username: &'navbar Signal<String>,
is_logged_in: &'navbar ReadSignal<bool>,
subapp: String,
}Working code using the Builder API#[component]
fn NavBarEndMenu<'navbar, G: Html>(cx: Scope<'navbar>, props: NavBarProps<'navbar>) -> View<G> {
let subapp = props.subapp;
let login_url = format!("/public/{}/trigger_login", &subapp);
let logout_url = format!("/api/{}/trigger_logout", &subapp);
let root = div().class("navbar-end");
root.dyn_if(
|| *props.is_logged_in.get(),
move || {
let logout_url = logout_url.clone();
div()
.class("navbar-item has-dropdown is-hoverable")
.c(a()
.class("navbar-link")
.attr("href", "#")
.dyn_t(|| props.username.get().to_string()))
.c(div().class("navbar-dropdown").c(a()
.class("navbar-item")
.dyn_attr("href", move || Some(logout_url.clone()))
.attr("rel", "external")
.t("Logout")))
},
move || {
let login_url = login_url.clone();
a().class("button is-black")
.dyn_attr("href", move || Some(login_url.clone()))
.attr("rel", "external")
.t("Login")
},
)
.view(cx)
} |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
|
This is because the |
Beta Was this translation helpful? Give feedback.
-
|
Thanks for the detailed explanation about the chaining of closures. Was not aware of |
Beta Was this translation helpful? Give feedback.

This is because the
(...)in the view! macro implicitly creates amove ||closure. and so does thehref=.... This means that the value is moved into the first closure and then moved into the second closure which is not allowed because that would make the first one aFnOnce. One way to solve this is to either clonelogout_urlright before theifandelsebut inside the(...). Another way is to uselogout_url = create_ref(format!(...))instead and uselogout_url.to_string()instead.