Children
General usage
Most of the time, when allowing a component to have children, you don't care what type of children the component has. In such cases, the below example will suffice.
use yew::{html, Children, Component, Html, Properties};
#[derive(Properties, Clone)]
pub struct ListProps {
#[prop_or_default]
pub children: Children,
}
pub struct List {
props: ListProps,
}
impl Component for List {
type Properties = ListProps;
// ...
fn view(&self) -> Html {
html! {
<div class="list">
{ for self.props.children.iter() }
</div>
}
}
}
Advanced usage
Typed children
In cases where you want one type of component to be passed as children to your component,
you can use yew::html::ChildrenWithProps<T>
.
use yew::{html, ChildrenWithProps, Component, Html, Properties};
// ...
#[derive(Properties, Clone)]
pub struct ListProps {
#[prop_or_default]
pub children: ChildrenWithProps<Item>,
}
pub struct List {
props: ListProps,
}
impl Component for List {
type Properties = ListProps;
// ...
fn view(&self) -> Html {
html! {
<div class="list">
{ for self.props.children.iter() }
</div>
}
}
}
Enum typed children
Of course, sometimes you might need to restrict the children to a few different components. In these cases, you have to get a little more hands-on with Yew.
The derive_more
crate is used here
for better ergonomics. If you don't want to use it, you can manually implement
From
for each variant.
use yew::{
html, html::ChildrenRenderer, virtual_dom::VChild,
Component, Html, Properties
};
// `derive_more::From` implements `From<VChild<Primary>>` and
// `From<VChild<Secondary>>` for `Item` automatically!
#[derive(Clone, derive_more::From)]
pub enum Item {
Primary(VChild<Primary>),
Secondary(VChild<Secondary>),
}
// Now, we implement `Into<Html>` so that yew knows how to render `Item`.
impl Into<Html> for Item {
fn into(self) -> Html {
match self {
Self::Primary(child) => child.into(),
Self::Secondary(child) => child.into(),
}
}
}
#[derive(Properties, Clone)]
pub struct ListProps {
#[prop_or_default]
pub children: ChildrenRenderer<Item>,
}
pub struct List {
props: ListProps,
}
impl Component for List {
type Properties = ListProps;
// ...
fn view(&self) -> Html {
html! {
<div class="list">
{ for self.props.children.iter() }
</div>
}
}
}
Optional typed child
You can also have a single optional child component of a specific type too:
use yew::{html, virtual_dom::VChild, Component, Html, Properties};
#[derive(Clone, Properties)]
pub struct PageProps {
#[prop_or_default]
pub sidebar: Option<VChild<PageSideBar>>,
}
struct Page {
props: PageProps,
}
impl Component for Page {
type Properties = PageProps;
// ...
fn view(&self) -> Html {
html! {
<div class="page">
{ self.props.sidebar.clone().map(Html::from).unwrap_or_default() }
// ... page content
</div>
}
}
}
// The page component can be called either with the sidebar or without:
// Page without sidebar
html! {
<Page />
}
// Page with sidebar
html! {
<Page sidebar=html_nested! {
<PageSideBar />
} />
}