Skip to content

Commit 2b996c2

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 2b996c2

4 files changed

Lines changed: 32 additions & 9 deletions

File tree

Cargo.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/yew-macro/tests/html_macro/element-fail.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -491,8 +491,8 @@ error[E0277]: the trait bound `Option<NotToString>: IntoPropValue<Option<implici
491491
`Option<F>` implements `IntoPropValue<Option<yew::Callback<I, O>>>`
492492
`Option<Rc<str>>` implements `IntoPropValue<Option<implicit_clone::unsync::string::IString>>`
493493
`Option<String>` implements `IntoPropValue<Option<implicit_clone::unsync::string::IString>>`
494+
`Option<T>` implements `IntoPropValue<VNode>`
494495
`Option<VChild<T>>` implements `IntoPropValue<Option<ChildrenRenderer<C>>>`
495-
`Option<VNode>` implements `IntoPropValue<VNode>`
496496

497497
error[E0277]: the trait bound `Option<{integer}>: IntoPropValue<Option<implicit_clone::unsync::string::IString>>` is not satisfied
498498
--> tests/html_macro/element-fail.rs:48:22
@@ -510,8 +510,8 @@ error[E0277]: the trait bound `Option<{integer}>: IntoPropValue<Option<implicit_
510510
`Option<F>` implements `IntoPropValue<Option<yew::Callback<I, O>>>`
511511
`Option<Rc<str>>` implements `IntoPropValue<Option<implicit_clone::unsync::string::IString>>`
512512
`Option<String>` implements `IntoPropValue<Option<implicit_clone::unsync::string::IString>>`
513+
`Option<T>` implements `IntoPropValue<VNode>`
513514
`Option<VChild<T>>` implements `IntoPropValue<Option<ChildrenRenderer<C>>>`
514-
`Option<VNode>` implements `IntoPropValue<VNode>`
515515

516516
error[E0277]: the trait bound `{integer}: IntoEventCallback<MouseEvent>` is not satisfied
517517
--> tests/html_macro/element-fail.rs:51:28
@@ -627,8 +627,8 @@ error[E0277]: the trait bound `Option<yew::NodeRef>: IntoPropValue<yew::NodeRef>
627627
`Option<F>` implements `IntoPropValue<Option<yew::Callback<I, O>>>`
628628
`Option<Rc<str>>` implements `IntoPropValue<Option<implicit_clone::unsync::string::IString>>`
629629
`Option<String>` implements `IntoPropValue<Option<implicit_clone::unsync::string::IString>>`
630+
`Option<T>` implements `IntoPropValue<VNode>`
630631
`Option<VChild<T>>` implements `IntoPropValue<Option<ChildrenRenderer<C>>>`
631-
`Option<VNode>` implements `IntoPropValue<VNode>`
632632

633633
error[E0277]: the trait bound `yew::Callback<String>: IntoEventCallback<MouseEvent>` is not satisfied
634634
--> tests/html_macro/element-fail.rs:58:29

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

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

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

128139
fn main() {}

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

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,10 @@ 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).unwrap_or_default()
221221
}
222222
}
223223

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

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

0 commit comments

Comments
 (0)