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}