mirror of
https://github.com/yewstack/yew.git
synced 2025-12-08 21:26:25 +00:00
* Add doc-test to test website code snippets Heavily inspired by tokio-rs/website repo. * Fix code snippets to pass doc tests Some code snippets are explicitly ignored and some are not run to avoid having to include dependencies for one liners. * Add website code snippet tests to CI * Fix CI * Remove doc-test from workspace * Exclude doc-test from workspace * Refactor code snippets and tests Code snippets can import types from doc_test crate i.e.: ```rust use doc_test::agents::EventBus; ``` This allows for moving some boilerplate away from the example and still checks that the code compiles correctly. Also some slight changes to some of the examples and the information about `ComponentLink` which is deprecated. * Move doc-test to packages * Rename doc-test crate to website-test The new name makes it more clear the purpose of this crate. * fix ci
4.9 KiB
4.9 KiB
| title | description |
|---|---|
| Components | Create complex layouts with component hierarchies |
Basic
Any type that implements Component can be used in the html! macro:
use yew::{Component, Html, html, Context, Properties};
struct MyComponent;
impl Component for MyComponent {
type Message = ();
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn view(&self, _ctx: &Context<Self>) -> Html {
html! {
{ "This component has no properties!" }
}
}
}
#[derive(PartialEq, Properties)]
struct Props {
prop1: String,
prop2: String,
}
struct MyComponentWithProps;
impl Component for MyComponentWithProps {
type Message = ();
type Properties = Props;
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn view(&self, ctx: &Context<Self>) -> Html {
html! {
{
format!(
"prop1: {} and prop2: {}",
ctx.props().prop1,
ctx.props().prop2
)
}
}
}
}
let props = Props {
prop1: "Hello".to_owned(),
prop2: "World".to_owned(),
};
html!{
<>
// No properties
<MyComponent />
// With Properties
<MyComponentWithProps prop1="lorem" prop2="ipsum" />
// With the whole set of props provided at once
<MyComponentWithProps with props />
</>
};
Nested
Components can be passed children if they have a children field in their Properties.
use yew::{Children, Component, Context, html, Html, Properties};
#[derive(PartialEq, Properties)]
struct Props {
id: String,
children: Children,
}
struct Container;
impl Component for Container {
type Message = ();
type Properties = Props;
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<div id={ctx.props().id.clone()}>
{ ctx.props().children.clone() }
</div>
}
}
}
html! {
<Container id="container">
<h4>{ "Hi" }</h4>
<div>{ "Hello" }</div>
</Container>
};
When using the with props syntax, the children passed in the html! macro overwrite the ones already present in the props.
use yew::{Children, Component, Context, html, Html, props, Properties};
#[derive(PartialEq, Properties)]
struct Props {
id: String,
children: Children,
}
struct Container;
impl Component for Container {
type Message = ();
type Properties = Props;
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<div id={ctx.props().id.clone()}>
{ ctx.props().children.clone() }
</div>
}
}
}
let props = yew::props!(Container::Properties {
id: "container-2",
children: Children::default(),
});
html! {
<Container with 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::{html, ChildrenWithProps, Component, Context, Html, Properties};
#[derive(Clone, PartialEq, Properties)]
pub struct ListItemProps {
value: String,
}
pub struct ListItem;
impl Component for ListItem {
type Message = ();
type Properties = ListItemProps;
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<span>
{ ctx.props().value.clone() }
</span>
}
}
}
#[derive(PartialEq, Properties)]
pub struct Props {
pub children: ChildrenWithProps<ListItem>,
}
pub struct List;
impl Component for List {
type Message = ();
type Properties = Props;
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn view(&self, ctx: &Context<Self>) -> Html {
html! {{
for ctx.props().children.iter().map(|mut item| {
let mut props = Rc::make_mut(&mut item.props);
props.value = format!("item-{}", props.value);
item
})
}}
}
}
html! {
<List>
<ListItem value="a" />
<ListItem value="b" />
<ListItem value="c" />
</List>
};