Components
Basic
Components can be used in the html!
macro:
use yew::prelude::*;
#[function_component]
fn MyComponent() -> Html {
html! {
{ "This component has no properties!" }
}
}
#[derive(Clone, PartialEq, Properties)]
struct Props {
user_first_name: String,
user_last_name: String,
}
#[function_component]
fn MyComponentWithProps(props: &Props) -> Html {
let Props { user_first_name, user_last_name } = props;
html! {
<>{"user_first_name: "}{user_first_name}{" and user_last_name: "}{user_last_name}</>
}
}
let props = Props {
user_first_name: "Bob".to_owned(),
user_last_name: "Smith".to_owned(),
};
html!{
<>
// No properties
<MyComponent />
// With Properties
<MyComponentWithProps user_first_name="Sam" user_last_name="Idle" />
// With the whole set of props provided at once
<MyComponentWithProps ..props.clone() />
// With Properties from a variable and specific values overridden
<MyComponentWithProps user_last_name="Elm" ..props />
</>
};
Nested
Components can be passed children if they have a children
field in their Properties
.
use yew::prelude::*;
#[derive(PartialEq, Properties)]
struct Props {
id: String,
children: Children,
}
#[function_component]
fn Container(props: &Props) -> Html {
html! {
<div id={props.id.clone()}>
{ props.children.clone() }
</div>
}
}
html! {
<Container id="container">
<h4>{ "Hi" }</h4>
<div>{ "Hello" }</div>
</Container>
};
The html!
macro allows you to pass a base expression with the ..props
syntax instead of specifying each property individually,
similar to Rust's Functional Update Syntax.
This base expression must occur after any individual props are passed.
When passing a base props expression with a children
field, the children passed in the html!
macro overwrite the ones already present in the props.
use yew::prelude::*;
#[derive(PartialEq, Properties)]
struct Props {
id: String,
children: Children,
}
#[function_component]
fn Container(props: &Props) -> Html {
html! {
<div id={props.id.clone()}>
{ props.children.clone() }
</div>
}
}
let props = yew::props!(Props {
id: "container-2",
children: Children::default(),
});
html! {
<Container ..props>
// props.children will be overwritten with this
<span>{ "I am a child, as you can see" }</span>
</Container>
};
Nested Children with Props
Nested component properties can be accessed and mutated if the containing component types its children. In the following example, the List
component can wrap ListItem
components. For a real world example of this pattern, check out the yew-router
source code. For a more advanced example, check out the nested-list
example in the main yew repository.
use std::rc::Rc;
use yew::prelude::*;
#[derive(Clone, PartialEq, Properties)]
pub struct ListItemProps {
value: String,
}
#[function_component]
fn ListItem(props: &ListItemProps) -> Html {
let ListItemProps { value } = props.clone();
html! {
<span>
{value}
</span>
}
}
#[derive(PartialEq, Properties)]
pub struct Props {
pub children: ChildrenWithProps<ListItem>,
}
#[function_component]
fn List(props: &Props) -> Html {
let modified_children = props.children.iter().map(|mut item| {
let mut props = Rc::make_mut(&mut item.props);
props.value = format!("item-{}", props.value);
item
});
html! { for modified_children }
}
html! {
<List>
<ListItem value="a" />
<ListItem value="b" />
<ListItem value="c" />
</List>
};