From ea8a530454f2bd82637cff1f4494d37e4d93e95d Mon Sep 17 00:00:00 2001 From: Finn Bear Date: Sun, 27 Mar 2022 15:43:53 -0700 Subject: [PATCH] Fix #2553 - automatically convert closure to callback for component properties (#2554) * Fix #2553 - automatically convert closure to callback for component properties. * Support F -> Option> too. * test stderr. --- .../tests/html_macro/component-fail.stderr | 4 +- .../tests/html_macro/element-fail.stderr | 3 ++ packages/yew/src/html/conversion.rs | 38 +++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/packages/yew-macro/tests/html_macro/component-fail.stderr b/packages/yew-macro/tests/html_macro/component-fail.stderr index 3a0eb2af361..5374e76ba40 100644 --- a/packages/yew-macro/tests/html_macro/component-fail.stderr +++ b/packages/yew-macro/tests/html_macro/component-fail.stderr @@ -346,7 +346,7 @@ error[E0277]: the trait bound `{integer}: IntoPropValue` is not satisfie <&'static str as IntoPropValue> <&'static str as IntoPropValue>> <&'static str as IntoPropValue>> - and 15 others + and 18 others error[E0277]: the trait bound `{integer}: IntoPropValue` is not satisfied --> tests/html_macro/component-fail.rs:79:34 @@ -359,7 +359,7 @@ error[E0277]: the trait bound `{integer}: IntoPropValue` is not satisfie <&'static str as IntoPropValue> <&'static str as IntoPropValue>> <&'static str as IntoPropValue>> - and 15 others + and 18 others error[E0308]: mismatched types --> tests/html_macro/component-fail.rs:80:31 diff --git a/packages/yew-macro/tests/html_macro/element-fail.stderr b/packages/yew-macro/tests/html_macro/element-fail.stderr index 5c2652e2680..61b85a3fc60 100644 --- a/packages/yew-macro/tests/html_macro/element-fail.stderr +++ b/packages/yew-macro/tests/html_macro/element-fail.stderr @@ -303,6 +303,7 @@ error[E0277]: the trait bound `Option: IntoPropValue as IntoPropValue>> as IntoPropValue>> + as IntoPropValue>>> as IntoPropValue>> > as IntoPropValue>> note: required by `into_prop_value` @@ -320,6 +321,7 @@ error[E0277]: the trait bound `Option<{integer}>: IntoPropValue as IntoPropValue>> as IntoPropValue>> + as IntoPropValue>>> as IntoPropValue>> > as IntoPropValue>> note: required by `into_prop_value` @@ -416,6 +418,7 @@ error[E0277]: the trait bound `Option: IntoPropValue = help: the following implementations were found: as IntoPropValue>> as IntoPropValue>> + as IntoPropValue>>> as IntoPropValue>> > as IntoPropValue>> note: required by `into_prop_value` diff --git a/packages/yew/src/html/conversion.rs b/packages/yew/src/html/conversion.rs index aa0b6c7d077..62408ab64d5 100644 --- a/packages/yew/src/html/conversion.rs +++ b/packages/yew/src/html/conversion.rs @@ -1,3 +1,4 @@ +use super::super::callback::Callback; use super::{Component, NodeRef, Scope}; use crate::virtual_dom::AttrValue; use std::rc::Rc; @@ -64,6 +65,33 @@ where } } +impl IntoPropValue> for F +where + F: 'static + Fn(I) -> O, +{ + fn into_prop_value(self) -> Callback { + Callback::from(self) + } +} + +impl IntoPropValue>> for F +where + F: 'static + Fn(I) -> O, +{ + fn into_prop_value(self) -> Option> { + Some(Callback::from(self)) + } +} + +impl IntoPropValue>> for Option +where + F: 'static + Fn(I) -> O, +{ + fn into_prop_value(self) -> Option> { + self.map(|f| Callback::from(f)) + } +} + macro_rules! impl_into_prop { (|$value:ident: $from_ty:ty| -> $to_ty:ty { $conversion:expr }) => { // implement V -> T @@ -111,4 +139,14 @@ mod test { let _: Option = "foo".into_prop_value(); let _: Option = Rc::::from("foo").into_prop_value(); } + + #[test] + fn test_callback() { + let _: Callback = (|_: String| ()).into_prop_value(); + let _: Option> = (|_: String| ()).into_prop_value(); + let _: Option> = Some(|_: String| ()).into_prop_value(); + let _: Callback = (|s: String| s).into_prop_value(); + let _: Option> = (|s: String| s).into_prop_value(); + let _: Option> = Some(|s: String| s).into_prop_value(); + } }