Skip to content

Commit 67a05a7

Browse files
committed
fix: allow Option<String> and Option<AttrValue> as VNode children in html!
Generalize `IntoPropValue<VNode> for Option<VNode>` into a blanket `IntoPropValue<VNode> for Option<T>` where `T: IntoPropValue<VNode>`. The single-expression child path in the html! macro calls `IntoPropValue::<VNode>::into_prop_value()` directly, which only had an impl for `Option<VNode>`. This is a regression from the removal of the `ToHtml` trait, which had a blanket `Option<T: ToHtml>` impl.
1 parent ce72475 commit 67a05a7

2 files changed

Lines changed: 27 additions & 2 deletions

File tree

packages/yew-macro/tests/html_macro/html-element-pass.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,18 @@ fn compile_pass() {
123123

124124
let option_vnode = ::std::option::Option::Some(::yew::html! {});
125125
_ = ::yew::html! { <div>{option_vnode}</div> };
126+
127+
// Option<String> and Option<AttrValue> as single children
128+
let opt_string: ::std::option::Option<::std::string::String> =
129+
::std::option::Option::Some(::std::string::String::from("hello"));
130+
_ = ::yew::html! { <div>{opt_string}</div> };
131+
132+
let opt_attr: ::std::option::Option<::yew::AttrValue> =
133+
::std::option::Option::Some(::yew::AttrValue::Static("hello"));
134+
_ = ::yew::html! { <div>{opt_attr}</div> };
135+
136+
let opt_none: ::std::option::Option<::std::string::String> = ::std::option::Option::None;
137+
_ = ::yew::html! { <div>{opt_none}</div> };
126138
}
127139

128140
fn main() {}

packages/yew/src/html/conversion/into_prop_value.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,11 @@ impl IntoPropValue<VNode> for Vec<VNode> {
214214
}
215215
}
216216

217-
impl IntoPropValue<VNode> for Option<VNode> {
217+
impl<T: IntoPropValue<VNode>> IntoPropValue<VNode> for Option<T> {
218218
#[inline]
219219
fn into_prop_value(self) -> VNode {
220-
self.unwrap_or_default()
220+
self.map(IntoPropValue::into_prop_value)
221+
.unwrap_or_default()
221222
}
222223
}
223224

@@ -350,6 +351,18 @@ mod test {
350351
let _: Option<AttrValue> = Cow::Borrowed("foo").into_prop_value();
351352
}
352353

354+
#[test]
355+
fn test_option_to_vnode() {
356+
let _: VNode = Some(String::from("hello")).into_prop_value();
357+
let _: VNode = Some(AttrValue::Static("hello")).into_prop_value();
358+
let _: VNode = Option::<String>::None.into_prop_value();
359+
let _: VNode = Option::<AttrValue>::None.into_prop_value();
360+
let _: VNode = Some(VNode::default()).into_prop_value();
361+
let _: VNode = Option::<VNode>::None.into_prop_value();
362+
let _: VNode = Some(42u32).into_prop_value();
363+
let _: VNode = Some(true).into_prop_value();
364+
}
365+
353366
#[test]
354367
fn test_callback() {
355368
let _: Callback<String> = (|_: String| ()).into_prop_value();

0 commit comments

Comments
 (0)