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, Context, Html, Properties};

3. #[derive(Properties, PartialEq)]
4. pub struct ListProps {
5. #[prop_or_default]
6. pub children: Children,
7. }

9. pub struct List;

11. impl Component for List {
12. type Message = ();
13. type Properties = ListProps;

15. fn create(_ctx: &Context<Self>) -> Self {
16. Self
17. }

19. fn view(&self, ctx: &Context<Self>) -> Html {
20. html! {
21. <div class="list">
22. { for ctx.props().children.iter() }
23. </div>
24. }
25. }
26. }

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, Context, Html, Properties};

3. pub struct Item;

5. impl Component for Item {
6. type Message = ();
7. type Properties = ();

9. fn create(_ctx: &Context<Self>) -> Self {
10. Self
11. }

13. fn view(&self, _ctx: &Context<Self>) -> Html {
14. html! {
15. { "item" }
16. }
17. }
18. }

20. #[derive(Properties, PartialEq)]
21. pub struct ListProps {
22. #[prop_or_default]
23. pub children: ChildrenWithProps<Item>,
24. }

26. pub struct List;

28. impl Component for List {
29. type Message = ();
30. type Properties = ListProps;

32. fn create(_ctx: &Context<Self>) -> Self {
33. Self
34. }

36. fn view(&self, ctx: &Context<Self>) -> Html {
37. html! {
38. <div class="list">
39. { for ctx.props().children.iter() }
40. </div>
41. }
42. }
43. }

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, Component,
3. Context, Html, Properties,
4. };

6. pub struct Primary;

8. impl Component for Primary {
9. type Message = ();
10. type Properties = ();

12. fn create(_ctx: &Context<Self>) -> Self {
13. Self
14. }

16. fn view(&self, _ctx: &Context<Self>) -> Html {
17. html! {
18. { "Primary" }
19. }
20. }
21. }

23. pub struct Secondary;

25. impl Component for Secondary {
26. type Message = ();
27. type Properties = ();

29. fn create(_ctx: &Context<Self>) -> Self {
30. Self
31. }

33. fn view(&self, _ctx: &Context<Self>) -> Html {
34. html! {
35. { "Secondary" }
36. }
37. }
38. }

40. #[derive(Clone, derive_more::From, PartialEq)]
41. pub enum Item {
42. Primary(VChild<Primary>),
43. Secondary(VChild<Secondary>),
44. }

46. // Now, we implement `Into<Html>` so that yew knows how to render `Item`.
47. #[allow(clippy::from_over_into)]
48. impl Into<Html> for Item {
49. fn into(self) -> Html {
50. match self {
51. Self::Primary(child) => child.into(),
52. Self::Secondary(child) => child.into(),
53. }
54. }
55. }

57. #[derive(Properties, PartialEq)]
58. pub struct ListProps {
59. #[prop_or_default]
60. pub children: ChildrenRenderer<Item>,
61. }

63. pub struct List;

65. impl Component for List {
66. type Message = ();
67. type Properties = ListProps;

69. fn create(_ctx: &Context<Self>) -> Self {
70. Self
71. }

73. fn view(&self, ctx: &Context<Self>) -> Html {
74. html! {
75. <div class="list">
76. { for ctx.props().children.iter() }
77. </div>
78. }
79. }
80. }

Optional typed child

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

1. use yew::{
2. html, html_nested, virtual_dom::VChild, Component,
3. Context, Html, Properties
4. };

6. pub struct PageSideBar;

8. impl Component for PageSideBar {
9. type Message = ();
10. type Properties = ();

12. fn create(_ctx: &Context<Self>) -> Self {
13. Self
14. }

16. fn view(&self, _ctx: &Context<Self>) -> Html {
17. html! {
18. { "sidebar" }
19. }
20. }
21. }

23. #[derive(Properties, PartialEq)]
24. pub struct PageProps {
25. #[prop_or_default]
26. pub sidebar: Option<VChild<PageSideBar>>,
27. }

29. struct Page;

31. impl Component for Page {
32. type Message = ();
33. type Properties = PageProps;

35. fn create(_ctx: &Context<Self>) -> Self {
36. Self
37. }

39. fn view(&self, ctx: &Context<Self>) -> Html {
40. html! {
41. <div class="page">
42. { ctx.props().sidebar.clone().map(Html::from).unwrap_or_default() }
43. // ... page content
44. </div>
45. }
46. }
47. }

49. // The page component can be called either with the sidebar or without:

51. pub fn render_page(with_sidebar: bool) -> Html {
52. if with_sidebar {
53. // Page with sidebar
54. html! {
55. <Page sidebar={html_nested! {
56. <PageSideBar />
57. }} />
58. }
59. } else {
60. // Page without sidebar
61. html! {
62. <Page />
63. }
64. }
65. }