-
-
Notifications
You must be signed in to change notification settings - Fork 659
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: variable bindings on components and slots #1140
Conversation
Yes, this looks great. |
In case it's not obvious to anyone how this works, here's an example adapting the Basically rather than pub fn Await<T, Fut, FF, VF, V>(
cx: Scope,
/// A function that takes a [`Scope`] and returns the [`Future`](std::future::Future) that
/// will the component will `.await` before rendering.
future: FF,
/// If `true`, the component will use [`create_blocking_resource`], preventing
/// the HTML stream from returning anything before `future` has resolved.
#[prop(optional)]
blocking: bool,
/// A function that takes a [`Scope`] and a reference to the resolved data from the `future`
/// renders a view.
children: VF,
) -> impl IntoView
where
Fut: std::future::Future<Output = T> + 'static,
FF: Fn(Scope) -> Fut + 'static,
V: IntoView,
VF: Fn(Scope, &T) -> V + 'static,
T: Serializable + 'static,
{
let res = if blocking {
create_blocking_resource(cx, || (), move |_| future(cx))
} else {
create_resource(cx, || (), move |_| future(cx))
};
let view = store_value(cx, children);
view! { cx,
<Suspense fallback=|| ()>
{move || res.with(cx, |data| view.with_value(|view| view(cx, data)))}
</Suspense>
}
} Now it can be used like this view! { cx,
<Await
future=|_| fetch_monkeys(3)
bind:data
>
<p>{*data} " little monkeys, jumping on the bed."</p>
</Await>
} and I can provide whatever name to view! { cx,
<Await
future=|_| fetch_monkeys(3)
bind:stuff
>
<p>{*stuff} " little monkeys, jumping on the bed."</p>
</Await>
} |
Hi guys, awesome work. I am very interested in all "declarative components" innovations. But this PR was merged rapidly and left one discussion about application of new binding syntax unfinished. I originally left example with it in #943 (comment) <For
each=iter
key=|v| v
bind(item: u32) // <== new syntax
>
<p> {item} </p>
</For> I already made PR to rstml with implementation rs-tml/rstml#17 Why we need new syntax, and what does it solve?
@gbj In your example view! { cx,
<Await
future=|_| fetch_monkeys(3)
bind:stuff
>
<p>{*stuff} " little monkeys, jumping on the bed."</p>
</Await>
}
So supporting special bind syntax, can enhance usability view! { cx,
<Await
future=|_| get_typed_resource::<u32>() // this turbofish can be removed
bind:stuff // bind(stuff: &u32) can be used instead
>
<p>Received: {*stuff}</p>
</Await>
}
For iterating, over big struct, or when part of tuple is not so important, destructing can make code cleaner. struct Person {
id: UID
name: String,
age: u8,
}
let people_iter = /* ... */
/* ... */
view!{
<For
each=people_iter
key=|id| id
bind(Person { name, age, .. }: Person)
>
<p> {name} - {age} </p>
</For>
}
Without types, users can mess with binding order especially especially if they know, that in html attribute order has no meaning. <Component bind:x bind:y >
{x} {y}
</Component> @gbj @yuuma03 On your opinions, should we add new syntax, or current bind:var, is look good enough? |
@vldm In your example, personally I think disambiguating with the turbofish is actually preferable, as it puts the specification of the type firmly in the realm of normal Rust code, rather than in the I could get on board with the |
I see, yes currently attribute is a mix of html attribute with value expected to be valid rust expression.
It's neccessary in the same places where it necessary for closure. Modification of 1. For example, imagine generic component that draw sql table(or any row from it) which doesn't know it's output type (common practice for ORM). The component is only know how to draw row or table, and use
It can be reused to draw any data from db, but i am not sure how in current design on caller site, i can set T to be specific type.
I am not sure that supporting two style is realy a good idea, because it can confuse new users. What i'd prefer is to keep But anyway, last word is on you. If you think that it will not confuse users, i can create a PR with it, after carefully testing bind syntax in rstml. |
@vldm Since this syntax hasn't been released yet, I'm comfortable with changes since they won't be semver breaking at all. However, I'd suggest we take the conversation to a new issue. I understand the ORM example you're raising in theory, but am curious about how it would actually work (or not work) in practice. If you open an issue with a complete-but-not-compiling example I'd be happy to talk through the options. |
This should close #943.