Add yew-autoprops to website documentation (#3505)

This commit is contained in:
Cecile Tonglet 2023-12-22 08:06:27 +01:00 committed by GitHub
parent 1d889347a6
commit b25703a035
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 162 additions and 80 deletions

27
Cargo.lock generated
View File

@ -1675,13 +1675,24 @@ dependencies = [
[[package]] [[package]]
name = "implicit-clone" name = "implicit-clone"
version = "0.4.1" version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af3d77000817fd9e7db159e8d52ed9b5941a2cdbfbdc8ca646e59887ae2b2dd1" checksum = "fc06a255cbf402a52ae399c05a518c68c569c916ea11423620111df576b9b9bb"
dependencies = [ dependencies = [
"implicit-clone-derive",
"indexmap 2.0.2", "indexmap 2.0.2",
] ]
[[package]]
name = "implicit-clone-derive"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9311685eb9a34808bbb0608ad2fcab9ae216266beca5848613e95553ac914e3b"
dependencies = [
"quote",
"syn 2.0.38",
]
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "1.9.3" version = "1.9.3"
@ -3615,6 +3626,7 @@ dependencies = [
"weblog", "weblog",
"yew", "yew",
"yew-agent", "yew-agent",
"yew-autoprops",
"yew-router", "yew-router",
] ]
@ -3876,6 +3888,17 @@ dependencies = [
"yew-agent", "yew-agent",
] ]
[[package]]
name = "yew-autoprops"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58865a8f2470a6ad839274e05c9627170d32930f39a2348f8c425880a6131792"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.38",
]
[[package]] [[package]]
name = "yew-macro" name = "yew-macro"
version = "0.21.0" version = "0.21.0"

View File

@ -21,7 +21,7 @@ error[E0277]: the trait bound `Classes: From<{integer}>` is not satisfied
<Classes as From<&Option<T>>> <Classes as From<&Option<T>>>
<Classes as From<&String>> <Classes as From<&String>>
<Classes as From<&[T]>> <Classes as From<&[T]>>
<Classes as From<&implicit_clone::unsync::IString>> <Classes as From<&implicit_clone::unsync::string::IString>>
<Classes as From<Cow<'static, str>>> <Classes as From<Cow<'static, str>>>
<Classes as From<Option<T>>> <Classes as From<Option<T>>>
<Classes as From<String>> <Classes as From<String>>
@ -44,7 +44,7 @@ error[E0277]: the trait bound `Classes: From<{float}>` is not satisfied
<Classes as From<&Option<T>>> <Classes as From<&Option<T>>>
<Classes as From<&String>> <Classes as From<&String>>
<Classes as From<&[T]>> <Classes as From<&[T]>>
<Classes as From<&implicit_clone::unsync::IString>> <Classes as From<&implicit_clone::unsync::string::IString>>
<Classes as From<Cow<'static, str>>> <Classes as From<Cow<'static, str>>>
<Classes as From<Option<T>>> <Classes as From<Option<T>>>
<Classes as From<String>> <Classes as From<String>>
@ -67,7 +67,7 @@ error[E0277]: the trait bound `Classes: From<{integer}>` is not satisfied
<Classes as From<&Option<T>>> <Classes as From<&Option<T>>>
<Classes as From<&String>> <Classes as From<&String>>
<Classes as From<&[T]>> <Classes as From<&[T]>>
<Classes as From<&implicit_clone::unsync::IString>> <Classes as From<&implicit_clone::unsync::string::IString>>
<Classes as From<Cow<'static, str>>> <Classes as From<Cow<'static, str>>>
<Classes as From<Option<T>>> <Classes as From<Option<T>>>
<Classes as From<String>> <Classes as From<String>>
@ -93,7 +93,7 @@ error[E0277]: the trait bound `Classes: From<{integer}>` is not satisfied
<Classes as From<&Option<T>>> <Classes as From<&Option<T>>>
<Classes as From<&String>> <Classes as From<&String>>
<Classes as From<&[T]>> <Classes as From<&[T]>>
<Classes as From<&implicit_clone::unsync::IString>> <Classes as From<&implicit_clone::unsync::string::IString>>
<Classes as From<Cow<'static, str>>> <Classes as From<Cow<'static, str>>>
<Classes as From<Option<T>>> <Classes as From<Option<T>>>
<Classes as From<String>> <Classes as From<String>>
@ -119,7 +119,7 @@ error[E0277]: the trait bound `Classes: From<u32>` is not satisfied
<Classes as From<&Option<T>>> <Classes as From<&Option<T>>>
<Classes as From<&String>> <Classes as From<&String>>
<Classes as From<&[T]>> <Classes as From<&[T]>>
<Classes as From<&implicit_clone::unsync::IString>> <Classes as From<&implicit_clone::unsync::string::IString>>
<Classes as From<Cow<'static, str>>> <Classes as From<Cow<'static, str>>>
<Classes as From<Option<T>>> <Classes as From<Option<T>>>
<Classes as From<String>> <Classes as From<String>>
@ -145,7 +145,7 @@ error[E0277]: the trait bound `Classes: From<{integer}>` is not satisfied
<Classes as From<&Option<T>>> <Classes as From<&Option<T>>>
<Classes as From<&String>> <Classes as From<&String>>
<Classes as From<&[T]>> <Classes as From<&[T]>>
<Classes as From<&implicit_clone::unsync::IString>> <Classes as From<&implicit_clone::unsync::string::IString>>
<Classes as From<Cow<'static, str>>> <Classes as From<Cow<'static, str>>>
<Classes as From<Option<T>>> <Classes as From<Option<T>>>
<Classes as From<String>> <Classes as From<String>>

View File

@ -396,76 +396,76 @@ note: function defined here
| pub fn __ensure_type<T>(_: T) {} | pub fn __ensure_type<T>(_: T) {}
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
error[E0277]: the trait bound `(): IntoPropValue<Option<implicit_clone::unsync::IString>>` is not satisfied error[E0277]: the trait bound `(): IntoPropValue<Option<implicit_clone::unsync::string::IString>>` is not satisfied
--> tests/html_macro/element-fail.rs:43:26 --> tests/html_macro/element-fail.rs:43:26
| |
43 | html! { <input type={()} /> }; 43 | html! { <input type={()} /> };
| ^^ the trait `IntoPropValue<Option<implicit_clone::unsync::IString>>` is not implemented for `()` | ^^ the trait `IntoPropValue<Option<implicit_clone::unsync::string::IString>>` is not implemented for `()`
| |
= help: the trait `IntoPropValue<VNode>` is implemented for `()` = help: the trait `IntoPropValue<VNode>` is implemented for `()`
error[E0277]: the trait bound `(): IntoPropValue<Option<implicit_clone::unsync::IString>>` is not satisfied error[E0277]: the trait bound `(): IntoPropValue<Option<implicit_clone::unsync::string::IString>>` is not satisfied
--> tests/html_macro/element-fail.rs:44:27 --> tests/html_macro/element-fail.rs:44:27
| |
44 | html! { <input value={()} /> }; 44 | html! { <input value={()} /> };
| ^^ the trait `IntoPropValue<Option<implicit_clone::unsync::IString>>` is not implemented for `()` | ^^ the trait `IntoPropValue<Option<implicit_clone::unsync::string::IString>>` is not implemented for `()`
| |
= help: the trait `IntoPropValue<VNode>` is implemented for `()` = help: the trait `IntoPropValue<VNode>` is implemented for `()`
error[E0277]: the trait bound `(): IntoPropValue<Option<implicit_clone::unsync::IString>>` is not satisfied error[E0277]: the trait bound `(): IntoPropValue<Option<implicit_clone::unsync::string::IString>>` is not satisfied
--> tests/html_macro/element-fail.rs:45:22 --> tests/html_macro/element-fail.rs:45:22
| |
45 | html! { <a href={()} /> }; 45 | html! { <a href={()} /> };
| ^^ the trait `IntoPropValue<Option<implicit_clone::unsync::IString>>` is not implemented for `()` | ^^ the trait `IntoPropValue<Option<implicit_clone::unsync::string::IString>>` is not implemented for `()`
| |
= help: the trait `IntoPropValue<VNode>` is implemented for `()` = help: the trait `IntoPropValue<VNode>` is implemented for `()`
error[E0277]: the trait bound `NotToString: IntoPropValue<Option<implicit_clone::unsync::IString>>` is not satisfied error[E0277]: the trait bound `NotToString: IntoPropValue<Option<implicit_clone::unsync::string::IString>>` is not satisfied
--> tests/html_macro/element-fail.rs:46:28 --> tests/html_macro/element-fail.rs:46:28
| |
46 | html! { <input string={NotToString} /> }; 46 | html! { <input string={NotToString} /> };
| ^^^^^^^^^^^ the trait `IntoPropValue<Option<implicit_clone::unsync::IString>>` is not implemented for `NotToString` | ^^^^^^^^^^^ the trait `IntoPropValue<Option<implicit_clone::unsync::string::IString>>` is not implemented for `NotToString`
| |
= help: the following other types implement trait `IntoPropValue<T>`: = help: the following other types implement trait `IntoPropValue<T>`:
<&'static [(K, V)] as IntoPropValue<implicit_clone::unsync::IMap<K, V>>> <&'static [(K, V)] as IntoPropValue<implicit_clone::unsync::map::IMap<K, V>>>
<&'static [T] as IntoPropValue<implicit_clone::unsync::IArray<T>>> <&'static [T] as IntoPropValue<implicit_clone::unsync::array::IArray<T>>>
<&'static str as IntoPropValue<Classes>> <&'static str as IntoPropValue<Classes>>
<&'static str as IntoPropValue<Option<String>>> <&'static str as IntoPropValue<Option<String>>>
<&'static str as IntoPropValue<Option<implicit_clone::unsync::IString>>> <&'static str as IntoPropValue<Option<implicit_clone::unsync::string::IString>>>
<&'static str as IntoPropValue<String>> <&'static str as IntoPropValue<String>>
<&'static str as IntoPropValue<implicit_clone::unsync::IString>> <&'static str as IntoPropValue<implicit_clone::unsync::string::IString>>
<&String as IntoPropValue<VNode>> <&String as IntoPropValue<VNode>>
and $N others and $N others
error[E0277]: the trait bound `Option<NotToString>: IntoPropValue<Option<implicit_clone::unsync::IString>>` is not satisfied error[E0277]: the trait bound `Option<NotToString>: IntoPropValue<Option<implicit_clone::unsync::string::IString>>` is not satisfied
--> tests/html_macro/element-fail.rs:47:23 --> tests/html_macro/element-fail.rs:47:23
| |
47 | html! { <a media={Some(NotToString)} /> }; 47 | html! { <a media={Some(NotToString)} /> };
| ^^^^ the trait `IntoPropValue<Option<implicit_clone::unsync::IString>>` is not implemented for `Option<NotToString>` | ^^^^ the trait `IntoPropValue<Option<implicit_clone::unsync::string::IString>>` is not implemented for `Option<NotToString>`
| |
= help: the following other types implement trait `IntoPropValue<T>`: = help: the following other types implement trait `IntoPropValue<T>`:
<Option<&'static str> as IntoPropValue<Option<String>>> <Option<&'static str> as IntoPropValue<Option<String>>>
<Option<&'static str> as IntoPropValue<Option<implicit_clone::unsync::IString>>> <Option<&'static str> as IntoPropValue<Option<implicit_clone::unsync::string::IString>>>
<Option<Cow<'static, str>> as IntoPropValue<Option<implicit_clone::unsync::IString>>> <Option<Cow<'static, str>> as IntoPropValue<Option<implicit_clone::unsync::string::IString>>>
<Option<F> as IntoPropValue<Option<yew::Callback<I, O>>>> <Option<F> as IntoPropValue<Option<yew::Callback<I, O>>>>
<Option<Rc<str>> as IntoPropValue<Option<implicit_clone::unsync::IString>>> <Option<Rc<str>> as IntoPropValue<Option<implicit_clone::unsync::string::IString>>>
<Option<String> as IntoPropValue<Option<implicit_clone::unsync::IString>>> <Option<String> as IntoPropValue<Option<implicit_clone::unsync::string::IString>>>
<Option<VChild<T>> as IntoPropValue<Option<ChildrenRenderer<C>>>> <Option<VChild<T>> as IntoPropValue<Option<ChildrenRenderer<C>>>>
<Option<VNode> as IntoPropValue<VNode>> <Option<VNode> as IntoPropValue<VNode>>
error[E0277]: the trait bound `Option<{integer}>: IntoPropValue<Option<implicit_clone::unsync::IString>>` is not satisfied error[E0277]: the trait bound `Option<{integer}>: IntoPropValue<Option<implicit_clone::unsync::string::IString>>` is not satisfied
--> tests/html_macro/element-fail.rs:48:22 --> tests/html_macro/element-fail.rs:48:22
| |
48 | html! { <a href={Some(5)} /> }; 48 | html! { <a href={Some(5)} /> };
| ^^^^ the trait `IntoPropValue<Option<implicit_clone::unsync::IString>>` is not implemented for `Option<{integer}>` | ^^^^ the trait `IntoPropValue<Option<implicit_clone::unsync::string::IString>>` is not implemented for `Option<{integer}>`
| |
= help: the following other types implement trait `IntoPropValue<T>`: = help: the following other types implement trait `IntoPropValue<T>`:
<Option<&'static str> as IntoPropValue<Option<String>>> <Option<&'static str> as IntoPropValue<Option<String>>>
<Option<&'static str> as IntoPropValue<Option<implicit_clone::unsync::IString>>> <Option<&'static str> as IntoPropValue<Option<implicit_clone::unsync::string::IString>>>
<Option<Cow<'static, str>> as IntoPropValue<Option<implicit_clone::unsync::IString>>> <Option<Cow<'static, str>> as IntoPropValue<Option<implicit_clone::unsync::string::IString>>>
<Option<F> as IntoPropValue<Option<yew::Callback<I, O>>>> <Option<F> as IntoPropValue<Option<yew::Callback<I, O>>>>
<Option<Rc<str>> as IntoPropValue<Option<implicit_clone::unsync::IString>>> <Option<Rc<str>> as IntoPropValue<Option<implicit_clone::unsync::string::IString>>>
<Option<String> as IntoPropValue<Option<implicit_clone::unsync::IString>>> <Option<String> as IntoPropValue<Option<implicit_clone::unsync::string::IString>>>
<Option<VChild<T>> as IntoPropValue<Option<ChildrenRenderer<C>>>> <Option<VChild<T>> as IntoPropValue<Option<ChildrenRenderer<C>>>>
<Option<VNode> as IntoPropValue<VNode>> <Option<VNode> as IntoPropValue<VNode>>
@ -567,11 +567,11 @@ error[E0277]: the trait bound `Option<yew::NodeRef>: IntoPropValue<yew::NodeRef>
| |
= help: the following other types implement trait `IntoPropValue<T>`: = help: the following other types implement trait `IntoPropValue<T>`:
<Option<&'static str> as IntoPropValue<Option<String>>> <Option<&'static str> as IntoPropValue<Option<String>>>
<Option<&'static str> as IntoPropValue<Option<implicit_clone::unsync::IString>>> <Option<&'static str> as IntoPropValue<Option<implicit_clone::unsync::string::IString>>>
<Option<Cow<'static, str>> as IntoPropValue<Option<implicit_clone::unsync::IString>>> <Option<Cow<'static, str>> as IntoPropValue<Option<implicit_clone::unsync::string::IString>>>
<Option<F> as IntoPropValue<Option<yew::Callback<I, O>>>> <Option<F> as IntoPropValue<Option<yew::Callback<I, O>>>>
<Option<Rc<str>> as IntoPropValue<Option<implicit_clone::unsync::IString>>> <Option<Rc<str>> as IntoPropValue<Option<implicit_clone::unsync::string::IString>>>
<Option<String> as IntoPropValue<Option<implicit_clone::unsync::IString>>> <Option<String> as IntoPropValue<Option<implicit_clone::unsync::string::IString>>>
<Option<VChild<T>> as IntoPropValue<Option<ChildrenRenderer<C>>>> <Option<VChild<T>> as IntoPropValue<Option<ChildrenRenderer<C>>>>
<Option<VNode> as IntoPropValue<VNode>> <Option<VNode> as IntoPropValue<VNode>>
= note: this error originates in the macro `html` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `html` (in Nightly builds, run with -Z macro-backtrace for more info)
@ -603,20 +603,20 @@ note: required by a bound in `yew::html::onclick::Wrapper::__macro_new`
| |_^ required by this bound in `yew::html::onclick::Wrapper::__macro_new` | |_^ required by this bound in `yew::html::onclick::Wrapper::__macro_new`
= note: this error originates in the macro `impl_action` which comes from the expansion of the macro `impl_short` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `impl_action` which comes from the expansion of the macro `impl_short` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: the trait bound `NotToString: IntoPropValue<Option<implicit_clone::unsync::IString>>` is not satisfied error[E0277]: the trait bound `NotToString: IntoPropValue<Option<implicit_clone::unsync::string::IString>>` is not satisfied
--> tests/html_macro/element-fail.rs:60:28 --> tests/html_macro/element-fail.rs:60:28
| |
60 | html! { <input string={NotToString} /> }; 60 | html! { <input string={NotToString} /> };
| ^^^^^^^^^^^ the trait `IntoPropValue<Option<implicit_clone::unsync::IString>>` is not implemented for `NotToString` | ^^^^^^^^^^^ the trait `IntoPropValue<Option<implicit_clone::unsync::string::IString>>` is not implemented for `NotToString`
| |
= help: the following other types implement trait `IntoPropValue<T>`: = help: the following other types implement trait `IntoPropValue<T>`:
<&'static [(K, V)] as IntoPropValue<implicit_clone::unsync::IMap<K, V>>> <&'static [(K, V)] as IntoPropValue<implicit_clone::unsync::map::IMap<K, V>>>
<&'static [T] as IntoPropValue<implicit_clone::unsync::IArray<T>>> <&'static [T] as IntoPropValue<implicit_clone::unsync::array::IArray<T>>>
<&'static str as IntoPropValue<Classes>> <&'static str as IntoPropValue<Classes>>
<&'static str as IntoPropValue<Option<String>>> <&'static str as IntoPropValue<Option<String>>>
<&'static str as IntoPropValue<Option<implicit_clone::unsync::IString>>> <&'static str as IntoPropValue<Option<implicit_clone::unsync::string::IString>>>
<&'static str as IntoPropValue<String>> <&'static str as IntoPropValue<String>>
<&'static str as IntoPropValue<implicit_clone::unsync::IString>> <&'static str as IntoPropValue<implicit_clone::unsync::string::IString>>
<&String as IntoPropValue<VNode>> <&String as IntoPropValue<VNode>>
and $N others and $N others
@ -629,15 +629,16 @@ error[E0277]: the trait bound `(): IntoPropValue<yew::NodeRef>` is not satisfied
= help: the trait `IntoPropValue<VNode>` is implemented for `()` = help: the trait `IntoPropValue<VNode>` is implemented for `()`
= note: this error originates in the macro `html` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `html` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: the trait bound `implicit_clone::unsync::IString: From<{integer}>` is not satisfied error[E0277]: the trait bound `implicit_clone::unsync::string::IString: From<{integer}>` is not satisfied
--> tests/html_macro/element-fail.rs:77:16 --> tests/html_macro/element-fail.rs:77:16
| |
77 | html! { <@{55}></@> }; 77 | html! { <@{55}></@> };
| ^^ the trait `From<{integer}>` is not implemented for `implicit_clone::unsync::IString` | ^^ the trait `From<{integer}>` is not implemented for `implicit_clone::unsync::string::IString`
| |
= help: the following other types implement trait `From<T>`: = help: the following other types implement trait `From<T>`:
<implicit_clone::unsync::IString as From<&'static str>> <implicit_clone::unsync::string::IString as From<&'static str>>
<implicit_clone::unsync::IString as From<Cow<'static, str>>> <implicit_clone::unsync::string::IString as From<&implicit_clone::unsync::string::IString>>
<implicit_clone::unsync::IString as From<Rc<str>>> <implicit_clone::unsync::string::IString as From<Cow<'static, str>>>
<implicit_clone::unsync::IString as From<String>> <implicit_clone::unsync::string::IString as From<Rc<str>>>
= note: required because of the requirements on the impl of `Into<implicit_clone::unsync::IString>` for `{integer}` <implicit_clone::unsync::string::IString as From<String>>
= note: required because of the requirements on the impl of `Into<implicit_clone::unsync::string::IString>` for `{integer}`

View File

@ -27,7 +27,7 @@ yew-macro = { version = "^0.21.0", path = "../yew-macro" }
thiserror = "1.0" thiserror = "1.0"
futures = { version = "0.3", default-features = false, features = ["std"] } futures = { version = "0.3", default-features = false, features = ["std"] }
html-escape = { version = "0.2.13", optional = true } html-escape = { version = "0.2.13", optional = true }
implicit-clone = { version = "0.4.1", features = ["map"] } implicit-clone = { version = "0.4.8", features = ["map"] }
base64ct = { version = "1.6.0", features = ["std"], optional = true } base64ct = { version = "1.6.0", features = ["std"], optional = true }
bincode = { version = "1.3.3", optional = true } bincode = { version = "1.3.3", optional = true }
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }

View File

@ -17,6 +17,7 @@ wasm-bindgen = "0.2"
wasm-bindgen-futures = "0.4" wasm-bindgen-futures = "0.4"
weblog = "0.3.0" weblog = "0.3.0"
yew = { path = "../../packages/yew/", features = ["ssr", "csr"] } yew = { path = "../../packages/yew/", features = ["ssr", "csr"] }
yew-autoprops = "0.4.1"
yew-router = { path = "../../packages/yew-router/" } yew-router = { path = "../../packages/yew-router/" }
tokio = { version = "1.33.0", features = ["rt", "macros"] } tokio = { version = "1.33.0", features = ["rt", "macros"] }

View File

@ -60,14 +60,14 @@ pub struct Props {
} }
#[function_component] #[function_component]
fn HelloWorld(props: &Props) -> Html { fn HelloWorld(&Props { is_loading }: &Props) -> Html {
html! { <>{"Am I loading? - "}{props.is_loading.clone()}</> } html! { <>{"Am I loading? - "}{is_loading}</> }
} }
// Then supply the prop // Then supply the prop
#[function_component] #[function_component]
fn App() -> Html { fn App() -> Html {
html! {<HelloWorld is_loading={true} />} html! { <HelloWorld is_loading=true /> }
} }
``` ```
@ -91,7 +91,7 @@ fn HelloWorld() -> Html {
// No props to supply // No props to supply
#[function_component] #[function_component]
fn App() -> Html { fn App() -> Html {
html! {<HelloWorld />} html! { <HelloWorld /> }
} }
``` ```
@ -126,8 +126,8 @@ pub struct Props {
} }
#[function_component] #[function_component]
fn HelloWorld(props: &Props) -> Html { fn HelloWorld(&Props { is_loading }: &Props) -> Html {
if props.is_loading.clone() { if is_loading {
html! { "Loading" } html! { "Loading" }
} else { } else {
html! { "Hello world" } html! { "Hello world" }
@ -137,12 +137,12 @@ fn HelloWorld(props: &Props) -> Html {
// Then use like this with default // Then use like this with default
#[function_component] #[function_component]
fn Case1() -> Html { fn Case1() -> Html {
html! {<HelloWorld />} html! { <HelloWorld /> }
} }
// Or no override the default // Or no override the default
#[function_component] #[function_component]
fn Case2() -> Html { fn Case2() -> Html {
html! {<HelloWorld is_loading={true} />} html! { <HelloWorld is_loading=true /> }
} }
``` ```
@ -154,30 +154,36 @@ For example, to default a boolean prop to `true`, use the attribute `#[prop_or(t
is evaluated when the properties are constructed and no explicit value has been given. is evaluated when the properties are constructed and no explicit value has been given.
```rust ```rust
use yew::{function_component, html, Html, Properties}; use yew::prelude::*;
#[derive(Properties, PartialEq)] #[derive(Properties, PartialEq)]
pub struct Props { pub struct Props {
#[prop_or_default]
pub is_loading: bool,
// highlight-start // highlight-start
#[prop_or("Bob".to_string())] #[prop_or(AttrValue::Static("Bob"))]
// highlight-end // highlight-end
pub name: String, pub name: AttrValue,
} }
#[function_component] #[function_component]
fn HelloWorld(props: &Props) -> Html { fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
html! {<>{"Hello world"}{props.name.clone()}</>} if is_loading {
html! { "Loading" }
} else {
html! { <>{"Hello "}{name} </>}
}
} }
// Then use like this with default // Then use like this with default
#[function_component] #[function_component]
fn Case1() -> Html { fn Case1() -> Html {
html! {<HelloWorld />} html! { <Hello /> }
} }
// Or no override the default // Or no override the default
#[function_component] #[function_component]
fn Case2() -> Html { fn Case2() -> Html {
html! {<HelloWorld name={"Sam".to_string()} />} html! { <Hello name="Sam" /> }
} }
``` ```
@ -188,34 +194,40 @@ Call `function` to initialize the prop value. `function` should have the signatu
The function is called when no explicit value has been given for that attribute. The function is called when no explicit value has been given for that attribute.
```rust ```rust
use yew::{function_component, html, Html, Properties}; use yew::prelude::*;
fn create_default_name() -> String { fn create_default_name() -> AttrValue {
"Bob".to_string() AttrValue::Static("Bob")
} }
#[derive(Properties, PartialEq)] #[derive(Properties, PartialEq)]
pub struct Props { pub struct Props {
#[prop_or_default]
pub is_loading: bool,
// highlight-start // highlight-start
#[prop_or_else(create_default_name)] #[prop_or_else(create_default_name)]
// highlight-end // highlight-end
pub name: String, pub name: AttrValue,
} }
#[function_component] #[function_component]
fn HelloWorld(props: &Props) -> Html { fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
html! {<>{"Hello world"}{props.name.clone()}</>} if is_loading {
html! { "Loading" }
} else {
html! { <>{"Hello "}{name}</> }
}
} }
// Then use like this with default // Then use like this with default
#[function_component] #[function_component]
fn Case1() -> Html { fn Case1() -> Html {
html! {<HelloWorld />} html! { <Hello /> }
} }
// Or no override the default // Or no override the default
#[function_component] #[function_component]
fn Case2() -> Html { fn Case2() -> Html {
html! {<HelloWorld name={"Sam".to_string()} />} html! { <Hello name="Sam" /> }
} }
``` ```
@ -239,30 +251,70 @@ The macro uses the same syntax as a struct expression except that you can't use
The type path can either point to the props directly (`path::to::Props`) or the associated properties of a component (`MyComp::Properties`). The type path can either point to the props directly (`path::to::Props`) or the associated properties of a component (`MyComp::Properties`).
```rust ```rust
use yew::{function_component, html, Html, Properties, props, virtual_dom::AttrValue}; use yew::prelude::*;
#[derive(Properties, PartialEq)] #[derive(Properties, PartialEq)]
pub struct Props { pub struct Props {
#[prop_or(AttrValue::from("Bob"))] #[prop_or_default]
pub is_loading: bool,
#[prop_or(AttrValue::Static("Bob"))]
pub name: AttrValue, pub name: AttrValue,
} }
#[function_component] #[function_component]
fn HelloWorld(props: &Props) -> Html { fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
html! {<>{"Hello world"}{props.name.clone()}</>} if is_loading {
html! { "Loading" }
} else {
html! { <>{"Hello "}{name}</> }
}
} }
#[function_component] #[function_component]
fn App() -> Html { fn App() -> Html {
// highlight-start // highlight-start
let pre_made_props = props! { let pre_made_props = yew::props! {
Props {} // Notice we did not need to specify name prop Props {} // Notice we did not need to specify name prop
}; };
// highlight-end // highlight-end
html! {<HelloWorld ..pre_made_props />} html! { <Hello ..pre_made_props /> }
} }
``` ```
## Automatically generate properties (yew-autoprops)
In order to streamline your development process, you can also use the macro
`#[autoprops]` (from the crate `yew-autoprops`) that will automatically
generate the `Properties` struct for you.
```rust
use yew::prelude::*;
use yew_autoprops::autoprops;
// the #[autoprops] macro must appear BEFORE #[function_component], the order matters
#[autoprops]
#[function_component]
fn Greetings(
#[prop_or_default]
is_loading: bool,
#[prop_or(AttrValue::Static("Hello"))]
message: &AttrValue,
#[prop_or(AttrValue::Static("World"))]
name: &AttrValue,
) -> Html {
if is_loading {
html! { "Loading" }
} else {
html! { <>{message}{" "}{name}</> }
}
}
// The properties struct "GreetingsProps" will be generated automatically.
//
// `is_loading` will be passed as value to the components while `message` and
// `name` will use references because of the leading `&` in the definition.
```
## Evaluation Order ## Evaluation Order
Props are evaluated in the order they're specified, as shown by the following example: Props are evaluated in the order they're specified, as shown by the following example:
@ -296,7 +348,12 @@ These include, but are not limited to:
**Why is this bad?** Interior mutability (such as with `RefCell`, `Mutex`, etc.) should **Why is this bad?** Interior mutability (such as with `RefCell`, `Mutex`, etc.) should
_generally_ be avoided. It can cause problems with re-renders (Yew doesn't know when the state has changed) _generally_ be avoided. It can cause problems with re-renders (Yew doesn't know when the state has changed)
so you may have to manually force a render. Like all things, it has its place. Use it with caution. so you may have to manually force a render. Like all things, it has its place. Use it with caution.
3. You tell us. Did you run into an edge-case you wish you knew about earlier? Feel free to create an issue 3. Using `Vec` type instead of `IArray`. <br />
**Why is this bad?** `Vec`, just like `String`, can also be expensive to clone. `IArray` is either
a reference-counted slice (`Rc<T>`) or a `&'static [T]`, thus very cheap to clone.<br />
**Note**: `IArray` can be imported from [implicit-clone](https://crates.io/crates/implicit-clone)
See that crate to learn more.
4. You tell us. Did you run into an edge-case you wish you knew about earlier? Feel free to create an issue
or PR a fix to this documentation. or PR a fix to this documentation.
## yew-autoprops ## yew-autoprops