-
-
Notifications
You must be signed in to change notification settings - Fork 590
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
Only elements are allowed at the top level of view! {}
macro
#55
Comments
Yeah the macro doesn't have any opinion about the type of what it's returning, although if you have multiple root nodes it should be wrapped in a fragment (<></>) The bigger issue here would be the type of what you're returning: if you had two elements you could return a Vec, but you have one Element and one Fn() -> Element. What would you hope the type would be that you're returning there? |
I'm not sure how it works under the hood, but I would expect the macro to call |
Yeah that would be one possible approach... It would return The I guess it would be possible to return each node as an enum of all the possible node types, but I kind of feel like that would be worse for most use cases. Sidebar: I know it's just a simple example, but in the example it's probably actually a better idea to do something like let focused = move || {
if focus() {
"focused"
} else {
"not focused"
}
};
view! { cx,
<div>
<input on:focus=move |_| set_focus(true) on:blur=move |_| set_focus(false) />
<p>{focused}</p>
</div>
} Because this causes only the text node inside the |
I think having an opaque type returned by I had originally structured the example like that on purpose to also demonstrate that I didn't see an easy way of returning an empty let helper_text = view! { cx,
if some_signal() {
view! { <label>The help is on the way</label> }
} else { view! { cx, } }
};
view! { cx,
<div class="form-control">
<label>"The input"</label>
<input />
{helper_text}
</div>
} |
In this specific case, what you probably want is to use an let helper_text = move || some_signal().then(|| {
view! { cx, <label>The help is on the way</label> }
});
view! { cx,
<div class="form-control">
<label>"The input"</label>
<input />
{helper_text}
</div>
} This actually works fine because |
That is correct, that is much better and what I did want to originally achieve. This, however, doesn't seem to be possible with the macro, perhaps you can shed light on how to achieve the same result without relying on wrapping with a fn Provider(cx: Scope) -> Element {
// ...
// Init the provider stuff
// ...
let children = move || {
is_initialized().then(|| {
provide_context(cx, ProvideCtx(/* ... */));
children()
})
};
view! { cx,
<span> // <-- ideally, remove these
{children}
</span> // <-- ideally, remove these
}
} I know the pattern above lends itself to be async, and thus should probably use A potential solution would be to not use the macro and change the |
I found a workaround which seems to work in the meantime. If we create a dummy component: #[component]
pub fn Fragment(cx: Scope, children: Box<dyn Fn() -> Vec<Element>>) -> Vec<Element> {
children()
} And then we use this in the view! {
<Fragment>
/* do your thing */
</Fragment>
} @gbj would this be a potential solution for this issue? To add a Edit: No, I see it does not, because the fragment returns a |
Re: the context provider example: Can't you achieve exactly what you're trying to achieve by simply returning More generally: Is the goal with the |
This almost works, except for two situations.
I presume point 2 is nil, but I play around with it and report back. 1. for sure doesn't work. |
You're right that this prevents you from doing that |
Why not impl |
I'd be open to doing this in the macro in certain circumstances: for example, if you're creating a fragment, and not every item is an element (so, your first example). This can be detected at macro time, and allows returning The larger issue, believe it or not, is that The whole DOM renderer is built on this type so I'll have to think about how it would work to handle it recursively. I think this may be a good compromise solution. |
Okay I just had an idea: if the fragment syntax I'm going to play around with that today and see if I can come up with a good solution that doesn't involve introducing another type and more runtime complexity. |
I'm going to close this issue for now... This is clearly what we're doing with #116 and we can archive this discussion. |
The following code is allowed:
but the following is not:
I do understand why, because the macro expects these items to be
Element
rather thanimpl IntoElement
, but thought it was worth mentioning in case this was not intentional.The text was updated successfully, but these errors were encountered: