yew_stdweb/html/component/children.rs
1//! Component children module
2
3use crate::html::Html;
4use crate::virtual_dom::{VChild, VNode};
5use std::fmt;
6
7/// A type used for accepting children elements in Component::Properties.
8///
9/// # Example
10/// **`model.rs`**
11///
12/// In this example, the `Wrapper` component is used to wrap other elements.
13/// ```
14///# use yew::{Children, Html, Properties, Component, ComponentLink, html};
15///# #[derive(Clone, Properties)]
16///# struct WrapperProps {
17///# children: Children,
18///# }
19///# struct Wrapper;
20///# impl Component for Wrapper{
21///# type Message = ();
22///# type Properties = WrapperProps;
23///# fn create(props: Self::Properties,link: ComponentLink<Self>) -> Self {unimplemented!()}
24///# fn update(&mut self,msg: Self::Message) -> bool {unimplemented!()}
25///# fn change(&mut self, _: Self::Properties) -> bool {unimplemented!()}
26///# // This is not a valid implementation. This is done for space convenience.
27///# fn view(&self) -> Html {
28/// html! {
29/// <Wrapper>
30/// <h4>{ "Hi" }</h4>
31/// <div>{ "Hello" }</div>
32/// </Wrapper>
33/// }
34///# }
35///# }
36/// ```
37///
38/// **`wrapper.rs`**
39///
40/// The Wrapper component must define a `children` property in order to wrap other elements. The
41/// children property can be used to render the wrapped elements.
42/// ```
43///# use yew::{Children, Html, Properties, Component, ComponentLink, html};
44/// #[derive(Clone, Properties)]
45/// struct WrapperProps {
46/// children: Children,
47/// }
48///
49///# struct Wrapper {props: WrapperProps};
50/// impl Component for Wrapper {
51/// // ...
52///# type Message = ();
53///# type Properties = WrapperProps;
54///# fn create(props: Self::Properties,link: ComponentLink<Self>) -> Self {unimplemented!()}
55///# fn update(&mut self,msg: Self::Message) -> bool {unimplemented!()}
56///# fn change(&mut self, _: Self::Properties) -> bool {unimplemented!()}
57/// fn view(&self) -> Html {
58/// html! {
59/// <div id="container">
60/// { self.props.children.clone() }
61/// </div>
62/// }
63/// }
64/// }
65/// ```
66pub type Children = ChildrenRenderer<Html>;
67
68/// A type used for accepting children elements in Component::Properties and accessing their props.
69///
70/// # Example
71/// **`model.rs`**
72///
73/// In this example, the `List` component can wrap `ListItem` components.
74/// ```
75///# use yew::{html, Component, Html, ComponentLink, ChildrenWithProps, Properties};
76///#
77///# #[derive(Clone, Properties)]
78///# struct ListProps {
79///# children: ChildrenWithProps<ListItem>,
80///# }
81///# struct List;
82///# impl Component for List {
83///# type Message = ();
84///# type Properties = ListProps;
85///# fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {unimplemented!()}
86///# fn update(&mut self, msg: Self::Message) -> bool {unimplemented!()}
87///# fn change(&mut self, _: Self::Properties) -> bool {unimplemented!()}
88///# fn view(&self) -> Html {unimplemented!()}
89///# }
90///# #[derive(Clone, Properties)]
91///# struct ListItemProps {
92///# value: String
93///# }
94///# struct ListItem;
95///# impl Component for ListItem {
96///# type Message = ();
97///# type Properties = ListItemProps;
98///# fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {unimplemented!()}
99///# fn update(&mut self, msg: Self::Message) -> bool {unimplemented!()}
100///# fn change(&mut self, _: Self::Properties) -> bool {unimplemented!()}
101///# fn view(&self) -> Html {unimplemented!()}
102///# }
103///# fn view() -> Html {
104/// html!{
105/// <List>
106/// <ListItem value="a" />
107/// <ListItem value="b" />
108/// <ListItem value="c" />
109/// </List>
110/// }
111///# }
112/// ```
113///
114/// **`list.rs`**
115///
116/// The `List` component must define a `children` property in order to wrap the list items. The
117/// `children` property can be used to filter, mutate, and render the items.
118/// ```
119///# use yew::{html, Component, Html, ChildrenWithProps, ComponentLink, Properties};
120///#
121/// #[derive(Clone, Properties)]
122/// struct ListProps {
123/// children: ChildrenWithProps<ListItem>,
124/// }
125///
126///# struct List {props: ListProps};
127/// impl Component for List {
128///# type Message = ();
129///# type Properties = ListProps;
130///# fn create(props: Self::Properties,link: ComponentLink<Self>) -> Self {unimplemented!()}
131///# fn update(&mut self,msg: Self::Message) -> bool {unimplemented!()}
132///# fn change(&mut self, _: Self::Properties) -> bool {unimplemented!()}
133/// // ...
134/// fn view(&self) -> Html {
135/// html!{{
136/// for self.props.children.iter().map(|mut item| {
137/// item.props.value = format!("item-{}", item.props.value);
138/// item
139/// })
140/// }}
141/// }
142/// }
143///#
144///# #[derive(Clone, Properties)]
145///# struct ListItemProps {
146///# #[prop_or_default]
147///# value: String
148///# }
149///#
150///# struct ListItem;
151///# impl Component for ListItem {
152///# type Message = ();
153///# type Properties = ListItemProps;
154///# fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {unimplemented!()}
155///# fn update(&mut self, msg: Self::Message) -> bool {unimplemented!()}
156///# fn change(&mut self, _: Self::Properties) -> bool {unimplemented!()}
157///# fn view(&self) -> Html {unimplemented!()}
158///# }
159/// ```
160pub type ChildrenWithProps<CHILD> = ChildrenRenderer<VChild<CHILD>>;
161
162/// A type used for rendering children html.
163#[derive(Clone)]
164pub struct ChildrenRenderer<T> {
165 children: Vec<T>,
166}
167
168impl<T: PartialEq> PartialEq for ChildrenRenderer<T> {
169 fn eq(&self, other: &Self) -> bool {
170 self.children == other.children
171 }
172}
173
174impl<T> ChildrenRenderer<T>
175where
176 T: Clone + Into<VNode>,
177{
178 /// Create children
179 pub fn new(children: Vec<T>) -> Self {
180 Self { children }
181 }
182
183 /// Children list is empty
184 pub fn is_empty(&self) -> bool {
185 self.children.is_empty()
186 }
187
188 /// Number of children elements
189 pub fn len(&self) -> usize {
190 self.children.len()
191 }
192
193 /// Render children components and return `Iterator`
194 pub fn iter(&self) -> impl Iterator<Item = T> + '_ {
195 // clone each child lazily.
196 // This way `self.iter().next()` only has to clone a single node.
197 self.children.iter().cloned()
198 }
199}
200
201impl<T> Default for ChildrenRenderer<T> {
202 fn default() -> Self {
203 Self {
204 children: Vec::new(),
205 }
206 }
207}
208
209impl<T> fmt::Debug for ChildrenRenderer<T> {
210 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
211 f.write_str("ChildrenRenderer<_>")
212 }
213}
214
215impl<T> IntoIterator for ChildrenRenderer<T> {
216 type Item = T;
217 type IntoIter = std::vec::IntoIter<Self::Item>;
218
219 fn into_iter(self) -> Self::IntoIter {
220 self.children.into_iter()
221 }
222}