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.

  1. use yew::{html, Children, Component, Html, Properties};
  2. #[derive(Properties, Clone)]
  3. pub struct ListProps {
  4. #[prop_or_default]
  5. pub children: Children,
  6. }
  7. pub struct List {
  8. props: ListProps,
  9. }
  10. impl Component for List {
  11. type Properties = ListProps;
  12. // ...
  13. fn view(&self) -> Html {
  14. html! {
  15. <div class="list">
  16. { for self.props.children.iter() }
  17. </div>
  18. }
  19. }
  20. }

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>.

  1. use yew::{html, ChildrenWithProps, Component, Html, Properties};
  2. // ...
  3. #[derive(Properties, Clone)]
  4. pub struct ListProps {
  5. #[prop_or_default]
  6. pub children: ChildrenWithProps<Item>,
  7. }
  8. pub struct List {
  9. props: ListProps,
  10. }
  11. impl Component for List {
  12. type Properties = ListProps;
  13. // ...
  14. fn view(&self) -> Html {
  15. html! {
  16. <div class="list">
  17. { for self.props.children.iter() }
  18. </div>
  19. }
  20. }
  21. }

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.

  1. use yew::{
  2. html, html::ChildrenRenderer, virtual_dom::VChild,
  3. Component, Html, Properties
  4. };
  5. // `derive_more::From` implements `From<VChild<Primary>>` and
  6. // `From<VChild<Secondary>>` for `Item` automatically!
  7. #[derive(Clone, derive_more::From)]
  8. pub enum Item {
  9. Primary(VChild<Primary>),
  10. Secondary(VChild<Secondary>),
  11. }
  12. // Now, we implement `Into<Html>` so that yew knows how to render `Item`.
  13. impl Into<Html> for Item {
  14. fn into(self) -> Html {
  15. match self {
  16. Self::Primary(child) => child.into(),
  17. Self::Secondary(child) => child.into(),
  18. }
  19. }
  20. }
  21. #[derive(Properties, Clone)]
  22. pub struct ListProps {
  23. #[prop_or_default]
  24. pub children: ChildrenRenderer<Item>,
  25. }
  26. pub struct List {
  27. props: ListProps,
  28. }
  29. impl Component for List {
  30. type Properties = ListProps;
  31. // ...
  32. fn view(&self) -> Html {
  33. html! {
  34. <div class="list">
  35. { for self.props.children.iter() }
  36. </div>
  37. }
  38. }
  39. }

Optional typed child

You can also have a single optional child component of a specific type too:

  1. use yew::{html, virtual_dom::VChild, Component, Html, Properties};
  2. #[derive(Clone, Properties)]
  3. pub struct PageProps {
  4. #[prop_or_default]
  5. pub sidebar: Option<VChild<PageSideBar>>,
  6. }
  7. struct Page {
  8. props: PageProps,
  9. }
  10. impl Component for Page {
  11. type Properties = PageProps;
  12. // ...
  13. fn view(&self) -> Html {
  14. html! {
  15. <div class="page">
  16. { self.props.sidebar.clone().map(Html::from).unwrap_or_default() }
  17. // ... page content
  18. </div>
  19. }
  20. }
  21. }
  22. // The page component can be called either with the sidebar or without:
  23. // Page without sidebar
  24. html! {
  25. <Page />
  26. }
  27. // Page with sidebar
  28. html! {
  29. <Page sidebar=html_nested! {
  30. <PageSideBar />
  31. } />
  32. }