Describe the feature you'd like
A clear and concise description of what you want to happen.
Currently a component can have children. However, with JSX you can also set a single component to a property, optionally:
~~~rust
pub struct Props {
pub children: ChildrenRenderer
#[prop_or_default]
pub sidebar: Option
}
~~~
Is your feature request related to a problem? Please describe. _(Optional)_
Currently you can do this is a list of children, but not with a single one.
You can achieve this currently only using Html:
~~~rust
pub struct Props {
pub children: ChildrenRenderer
#[prop_or_default]
pub sidebar: Html,
}
~~~
However, that doesn't ensure that the component is of a specific (required) type.
Questionnaire
This is already possible using VChild<COMP>:
use yew::{
prelude::*,
virtual_dom::VChild,
};
struct Sidebar;
impl Component for Sidebar {
// ...
}
#[derive(Clone, Properties)]
struct Model {
sidebar: VChild<Sidebar>,
}
impl Component for Model {
type Properties = Self;
fn create(props: Self::Properties, _link: ComponentLink<Self>) -> Self {
props
}
// ...
fn view(&self) -> Html {
let sidebar = Html::from(self.sidebar.clone());
html! {
<>
<nav>{ sidebar }</nav>
<main class="my-content">{ ... }</main>
</>
}
}
}
fn render() -> Html {
// create your beautiful sidebar
let sidebar = html_nested! { <Sidebar /> };
html! {
<Model sidebar=sidebar />
}
}
We should definitely document this better though!
@siku2 Thanks for the explanation! That should definitely go into the documentation. However it solves my issue only partly, as I am trying to add an optional component.
When use your example, I must provide a sidebar. When I wrap VChild<Sidebar> with Option<>, I get the following error:
~~~
error[E0277]: std::option::Option<yew::virtual_dom::VChild<pagesidebar::PageSidebar>> doesn't implement std::fmt::Display
--> src/page.rs:57:19
|
57 | { self.props.sidebar }
| ^^^^ std::option::Option<yew::virtual_dom::VChild<pagesidebar::PageSidebar>> cannot be formatted with the default formatter
|
= help: the trait std::fmt::Display is not implemented for std::option::Option<yew::virtual_dom::VChild<pagesidebar::PageSidebar>>
= note: in format strings you may be able to use {:?} (or {:#?} for pretty-print) instead
= note: required because of the requirements on the impl of std::string::ToString for std::option::Option<yew::virtual_dom::VChild<pagesidebar::PageSidebar>>
= note: required because of the requirements on the impl of std::convert::From<std::option::Option<yew::virtual_dom::VChild<pagesidebar::PageSidebar>>> for yew::virtual_dom::VNode
= note: required because of the requirements on the impl of std::convert::Into<yew::virtual_dom::VNode> for std::option::Option<yew::virtual_dom::VChild<pagesidebar::PageSidebar>>
= note: required because of the requirements on the impl of std::convert::From<std::option::Option<yew::virtual_dom::VChild<pagesidebar::PageSidebar>>> for yew::utils::NodeSeq<std::option::Option<yew::virtual_dom::VChild<pagesidebar::PageSidebar>>, yew::virtual_dom::VNode>
= note: required by std::convert::From::from
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
~~~
Ok, I was able to work around this using:
~~~rust
pub struct Props {
#[prop_or_default]
pub sidebar: Option
}
impl Component for Page {
fn view(&self) -> Html {
html! {
impl Page {
fn sidebar(&self) -> Html {
match &self.props.sidebar {
Some(sidebar) => Html::from(sidebar.clone()),
None => html! {},
}
}
}
~~~
You forgot to convert it to Html. Also, you can't use Option<T> directly.
You're looking for something like this:
html! { self.props.sidebar.clone().map(Html::from).unwrap_or_default() }
EDIT: of course you had to figure it out yourself before I finished my comment :smile:
You also can inline the html_nested:
~
html!{
}}>
}
~
@siku2 thanks for your help!
Most helpful comment
You forgot to convert it to
Html. Also, you can't useOption<T>directly.You're looking for something like this:
EDIT: of course you had to figure it out yourself before I finished my comment :smile: