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