mirror of
https://github.com/yewstack/yew.git
synced 2025-12-08 21:26:25 +00:00
Remove ToHtml trait (#3453)
* remove ToHtml trait * re-add display impls * make Vec::clone expilit * fix doc * fix conflicting impls Into<Html> and Display can't be implemented on the same type * update docs * blanket impl won't work here * bring back `Vec<VNode>: IntoPropValue<VNode>` * macro tests * Revert "fix conflicting impls" This reverts commit 52f3c1fa8174489ba9cc783d708a49cc7b9c90a4. These impls are fine now * make examples compile * .clone() should be before .into() * Rc VList * Make use of ImplicitClone and AttrValue in example (There is more work to do but it's complicated so I will do it in another PR) * Impl ImplicitClone on VChild --------- Co-authored-by: Cecile Tonglet <cecile.tonglet@cecton.com>
This commit is contained in:
parent
7f45af3a66
commit
0eb167ac78
@ -2,6 +2,7 @@ use std::rc::Rc;
|
|||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use strum_macros::{Display, EnumIter};
|
use strum_macros::{Display, EnumIter};
|
||||||
|
use yew::html::IntoPropValue;
|
||||||
use yew::prelude::*;
|
use yew::prelude::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
@ -42,8 +43,8 @@ impl Filter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToHtml for Filter {
|
impl IntoPropValue<Html> for Filter {
|
||||||
fn to_html(&self) -> Html {
|
fn into_prop_value(self) -> Html {
|
||||||
html! {<>{self.to_string()}</>}
|
html! {<>{self.to_string()}</>}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ pub struct Props {
|
|||||||
#[prop_or_default]
|
#[prop_or_default]
|
||||||
pub hide: bool,
|
pub hide: bool,
|
||||||
pub on_hover: Callback<Hovered>,
|
pub on_hover: Callback<Hovered>,
|
||||||
pub name: String,
|
pub name: AttrValue,
|
||||||
#[prop_or_default]
|
#[prop_or_default]
|
||||||
pub children: Children,
|
pub children: Children,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -73,9 +73,8 @@ impl List {
|
|||||||
.filter(|c| !c.props.hide)
|
.filter(|c| !c.props.hide)
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, mut c)| {
|
.map(|(i, mut c)| {
|
||||||
let mut props = (*c.props).clone();
|
let props = Rc::make_mut(&mut c.props);
|
||||||
props.name = format!("#{} - {}", i + 1, props.name);
|
props.name = format!("#{} - {}", i + 1, props.name).into();
|
||||||
c.props = Rc::new(props);
|
|
||||||
c
|
c
|
||||||
})
|
})
|
||||||
.collect::<Html>()
|
.collect::<Html>()
|
||||||
|
|||||||
@ -8,7 +8,7 @@ use std::fmt;
|
|||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use yew::html::{ImplicitClone, Scope};
|
use yew::html::{ImplicitClone, IntoPropValue, Scope};
|
||||||
use yew::prelude::*;
|
use yew::prelude::*;
|
||||||
|
|
||||||
pub struct WeakComponentLink<COMP: Component>(Rc<RefCell<Option<Scope<COMP>>>>);
|
pub struct WeakComponentLink<COMP: Component>(Rc<RefCell<Option<Scope<COMP>>>>);
|
||||||
@ -40,14 +40,16 @@ impl<COMP: Component> PartialEq for WeakComponentLink<COMP> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum Hovered {
|
pub enum Hovered {
|
||||||
Header,
|
Header,
|
||||||
Item(String),
|
Item(AttrValue),
|
||||||
List,
|
List,
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ImplicitClone for Hovered {}
|
||||||
|
|
||||||
impl fmt::Display for Hovered {
|
impl fmt::Display for Hovered {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
@ -63,8 +65,8 @@ impl fmt::Display for Hovered {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToHtml for Hovered {
|
impl IntoPropValue<Html> for &Hovered {
|
||||||
fn to_html(&self) -> yew::Html {
|
fn into_prop_value(self) -> Html {
|
||||||
html! {<>{self.to_string()}</>}
|
html! {<>{self.to_string()}</>}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -139,7 +139,7 @@ impl Component for App {
|
|||||||
{ &self.time }
|
{ &self.time }
|
||||||
</div>
|
</div>
|
||||||
<div id="messages">
|
<div id="messages">
|
||||||
{ for self.messages.iter().map(|message| html! { <p>{ message }</p> }) }
|
{ for self.messages.iter().map(|message| html! { <p>{ *message }</p> }) }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -105,7 +105,7 @@ fn App() -> Html {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|message| {
|
.map(|message| {
|
||||||
key += 1;
|
key += 1;
|
||||||
html! { <p key={ key }>{ message }</p> }
|
html! { <p key={ key }>{ *message }</p> }
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use strum_macros::{Display, EnumIter};
|
use strum_macros::{Display, EnumIter};
|
||||||
|
use yew::html::IntoPropValue;
|
||||||
use yew::prelude::*;
|
use yew::prelude::*;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
@ -142,8 +143,8 @@ impl Filter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToHtml for Filter {
|
impl IntoPropValue<Html> for Filter {
|
||||||
fn to_html(&self) -> yew::Html {
|
fn into_prop_value(self) -> yew::Html {
|
||||||
html! { <>{self.to_string()}</> }
|
html! { <>{self.to_string()}</> }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -463,16 +463,7 @@ error[E0277]: the trait bound `(): IntoPropValue<String>` is not satisfied
|
|||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
= help: the following other types implement trait `IntoPropValue<T>`:
|
= help: the trait `IntoPropValue<VNode>` is implemented for `()`
|
||||||
<&'static [(K, V)] as IntoPropValue<implicit_clone::unsync::IMap<K, V>>>
|
|
||||||
<&'static [T] as IntoPropValue<implicit_clone::unsync::IArray<T>>>
|
|
||||||
<&'static str as IntoPropValue<Classes>>
|
|
||||||
<&'static str as IntoPropValue<Option<String>>>
|
|
||||||
<&'static str as IntoPropValue<Option<implicit_clone::unsync::IString>>>
|
|
||||||
<&'static str as IntoPropValue<String>>
|
|
||||||
<&'static str as IntoPropValue<implicit_clone::unsync::IString>>
|
|
||||||
<&T as IntoPropValue<Option<T>>>
|
|
||||||
and $N others
|
|
||||||
note: required by a bound in `ChildPropertiesBuilder::string`
|
note: required by a bound in `ChildPropertiesBuilder::string`
|
||||||
--> tests/html_macro/component-fail.rs:4:17
|
--> tests/html_macro/component-fail.rs:4:17
|
||||||
|
|
|
|
||||||
@ -706,7 +697,9 @@ error[E0277]: the trait bound `yew::virtual_dom::VText: IntoPropValue<ChildrenRe
|
|||||||
117 | html! { <ChildContainer>{ "Not allowed" }</ChildContainer> };
|
117 | html! { <ChildContainer>{ "Not allowed" }</ChildContainer> };
|
||||||
| ^^^^^^^^^^^^^^ the trait `IntoPropValue<ChildrenRenderer<VChild<Child>>>` is not implemented for `yew::virtual_dom::VText`
|
| ^^^^^^^^^^^^^^ the trait `IntoPropValue<ChildrenRenderer<VChild<Child>>>` is not implemented for `yew::virtual_dom::VText`
|
||||||
|
|
|
|
||||||
= help: the trait `IntoPropValue<ChildrenRenderer<VNode>>` is implemented for `yew::virtual_dom::VText`
|
= help: the following other types implement trait `IntoPropValue<T>`:
|
||||||
|
<yew::virtual_dom::VText as IntoPropValue<ChildrenRenderer<VNode>>>
|
||||||
|
<yew::virtual_dom::VText as IntoPropValue<VNode>>
|
||||||
note: required by a bound in `ChildContainerPropertiesBuilder::children`
|
note: required by a bound in `ChildContainerPropertiesBuilder::children`
|
||||||
--> tests/html_macro/component-fail.rs:24:17
|
--> tests/html_macro/component-fail.rs:24:17
|
||||||
|
|
|
|
||||||
|
|||||||
@ -434,16 +434,7 @@ error[E0277]: the trait bound `(): IntoPropValue<Option<implicit_clone::unsync::
|
|||||||
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::IString>>` is not implemented for `()`
|
||||||
|
|
|
|
||||||
= help: the following other types implement trait `IntoPropValue<T>`:
|
= help: the trait `IntoPropValue<VNode>` is implemented for `()`
|
||||||
<&'static [(K, V)] as IntoPropValue<implicit_clone::unsync::IMap<K, V>>>
|
|
||||||
<&'static [T] as IntoPropValue<implicit_clone::unsync::IArray<T>>>
|
|
||||||
<&'static str as IntoPropValue<Classes>>
|
|
||||||
<&'static str as IntoPropValue<Option<String>>>
|
|
||||||
<&'static str as IntoPropValue<Option<implicit_clone::unsync::IString>>>
|
|
||||||
<&'static str as IntoPropValue<String>>
|
|
||||||
<&'static str as IntoPropValue<implicit_clone::unsync::IString>>
|
|
||||||
<&T as IntoPropValue<Option<T>>>
|
|
||||||
and $N others
|
|
||||||
|
|
||||||
error[E0277]: the trait bound `(): IntoPropValue<Option<implicit_clone::unsync::IString>>` is not satisfied
|
error[E0277]: the trait bound `(): IntoPropValue<Option<implicit_clone::unsync::IString>>` is not satisfied
|
||||||
--> tests/html_macro/element-fail.rs:44:27
|
--> tests/html_macro/element-fail.rs:44:27
|
||||||
@ -451,16 +442,7 @@ error[E0277]: the trait bound `(): IntoPropValue<Option<implicit_clone::unsync::
|
|||||||
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::IString>>` is not implemented for `()`
|
||||||
|
|
|
|
||||||
= help: the following other types implement trait `IntoPropValue<T>`:
|
= help: the trait `IntoPropValue<VNode>` is implemented for `()`
|
||||||
<&'static [(K, V)] as IntoPropValue<implicit_clone::unsync::IMap<K, V>>>
|
|
||||||
<&'static [T] as IntoPropValue<implicit_clone::unsync::IArray<T>>>
|
|
||||||
<&'static str as IntoPropValue<Classes>>
|
|
||||||
<&'static str as IntoPropValue<Option<String>>>
|
|
||||||
<&'static str as IntoPropValue<Option<implicit_clone::unsync::IString>>>
|
|
||||||
<&'static str as IntoPropValue<String>>
|
|
||||||
<&'static str as IntoPropValue<implicit_clone::unsync::IString>>
|
|
||||||
<&T as IntoPropValue<Option<T>>>
|
|
||||||
and $N others
|
|
||||||
|
|
||||||
error[E0277]: the trait bound `(): IntoPropValue<Option<implicit_clone::unsync::IString>>` is not satisfied
|
error[E0277]: the trait bound `(): IntoPropValue<Option<implicit_clone::unsync::IString>>` is not satisfied
|
||||||
--> tests/html_macro/element-fail.rs:45:22
|
--> tests/html_macro/element-fail.rs:45:22
|
||||||
@ -468,16 +450,7 @@ error[E0277]: the trait bound `(): IntoPropValue<Option<implicit_clone::unsync::
|
|||||||
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::IString>>` is not implemented for `()`
|
||||||
|
|
|
|
||||||
= help: the following other types implement trait `IntoPropValue<T>`:
|
= help: the trait `IntoPropValue<VNode>` is implemented for `()`
|
||||||
<&'static [(K, V)] as IntoPropValue<implicit_clone::unsync::IMap<K, V>>>
|
|
||||||
<&'static [T] as IntoPropValue<implicit_clone::unsync::IArray<T>>>
|
|
||||||
<&'static str as IntoPropValue<Classes>>
|
|
||||||
<&'static str as IntoPropValue<Option<String>>>
|
|
||||||
<&'static str as IntoPropValue<Option<implicit_clone::unsync::IString>>>
|
|
||||||
<&'static str as IntoPropValue<String>>
|
|
||||||
<&'static str as IntoPropValue<implicit_clone::unsync::IString>>
|
|
||||||
<&T as IntoPropValue<Option<T>>>
|
|
||||||
and $N others
|
|
||||||
|
|
||||||
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::IString>>` is not satisfied
|
||||||
--> tests/html_macro/element-fail.rs:46:28
|
--> tests/html_macro/element-fail.rs:46:28
|
||||||
@ -493,7 +466,7 @@ error[E0277]: the trait bound `NotToString: IntoPropValue<Option<implicit_clone:
|
|||||||
<&'static str as IntoPropValue<Option<implicit_clone::unsync::IString>>>
|
<&'static str as IntoPropValue<Option<implicit_clone::unsync::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::IString>>
|
||||||
<&T as IntoPropValue<Option<T>>>
|
<&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::IString>>` is not satisfied
|
||||||
@ -510,6 +483,7 @@ error[E0277]: the trait bound `Option<NotToString>: IntoPropValue<Option<implici
|
|||||||
<Option<Rc<str>> as IntoPropValue<Option<implicit_clone::unsync::IString>>>
|
<Option<Rc<str>> as IntoPropValue<Option<implicit_clone::unsync::IString>>>
|
||||||
<Option<String> as IntoPropValue<Option<implicit_clone::unsync::IString>>>
|
<Option<String> as IntoPropValue<Option<implicit_clone::unsync::IString>>>
|
||||||
<Option<VChild<T>> as IntoPropValue<Option<ChildrenRenderer<C>>>>
|
<Option<VChild<T>> as IntoPropValue<Option<ChildrenRenderer<C>>>>
|
||||||
|
<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::IString>>` is not satisfied
|
||||||
--> tests/html_macro/element-fail.rs:48:22
|
--> tests/html_macro/element-fail.rs:48:22
|
||||||
@ -525,6 +499,7 @@ error[E0277]: the trait bound `Option<{integer}>: IntoPropValue<Option<implicit_
|
|||||||
<Option<Rc<str>> as IntoPropValue<Option<implicit_clone::unsync::IString>>>
|
<Option<Rc<str>> as IntoPropValue<Option<implicit_clone::unsync::IString>>>
|
||||||
<Option<String> as IntoPropValue<Option<implicit_clone::unsync::IString>>>
|
<Option<String> as IntoPropValue<Option<implicit_clone::unsync::IString>>>
|
||||||
<Option<VChild<T>> as IntoPropValue<Option<ChildrenRenderer<C>>>>
|
<Option<VChild<T>> as IntoPropValue<Option<ChildrenRenderer<C>>>>
|
||||||
|
<Option<VNode> as IntoPropValue<VNode>>
|
||||||
|
|
||||||
error[E0277]: expected a `Fn<(MouseEvent,)>` closure, found `{integer}`
|
error[E0277]: expected a `Fn<(MouseEvent,)>` closure, found `{integer}`
|
||||||
--> tests/html_macro/element-fail.rs:51:28
|
--> tests/html_macro/element-fail.rs:51:28
|
||||||
@ -613,16 +588,7 @@ error[E0277]: the trait bound `(): IntoPropValue<yew::NodeRef>` is not satisfied
|
|||||||
56 | html! { <input ref={()} /> };
|
56 | html! { <input ref={()} /> };
|
||||||
| ^^ the trait `IntoPropValue<yew::NodeRef>` is not implemented for `()`
|
| ^^ the trait `IntoPropValue<yew::NodeRef>` is not implemented for `()`
|
||||||
|
|
|
|
||||||
= help: the following other types implement trait `IntoPropValue<T>`:
|
= help: the trait `IntoPropValue<VNode>` is implemented for `()`
|
||||||
<&'static [(K, V)] as IntoPropValue<implicit_clone::unsync::IMap<K, V>>>
|
|
||||||
<&'static [T] as IntoPropValue<implicit_clone::unsync::IArray<T>>>
|
|
||||||
<&'static str as IntoPropValue<Classes>>
|
|
||||||
<&'static str as IntoPropValue<Option<String>>>
|
|
||||||
<&'static str as IntoPropValue<Option<implicit_clone::unsync::IString>>>
|
|
||||||
<&'static str as IntoPropValue<String>>
|
|
||||||
<&'static str as IntoPropValue<implicit_clone::unsync::IString>>
|
|
||||||
<&T as IntoPropValue<Option<T>>>
|
|
||||||
and $N others
|
|
||||||
= 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 `Option<yew::NodeRef>: IntoPropValue<yew::NodeRef>` is not satisfied
|
error[E0277]: the trait bound `Option<yew::NodeRef>: IntoPropValue<yew::NodeRef>` is not satisfied
|
||||||
@ -639,6 +605,7 @@ error[E0277]: the trait bound `Option<yew::NodeRef>: IntoPropValue<yew::NodeRef>
|
|||||||
<Option<Rc<str>> as IntoPropValue<Option<implicit_clone::unsync::IString>>>
|
<Option<Rc<str>> as IntoPropValue<Option<implicit_clone::unsync::IString>>>
|
||||||
<Option<String> as IntoPropValue<Option<implicit_clone::unsync::IString>>>
|
<Option<String> as IntoPropValue<Option<implicit_clone::unsync::IString>>>
|
||||||
<Option<VChild<T>> as IntoPropValue<Option<ChildrenRenderer<C>>>>
|
<Option<VChild<T>> as IntoPropValue<Option<ChildrenRenderer<C>>>>
|
||||||
|
<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)
|
||||||
|
|
||||||
error[E0277]: expected a `Fn<(MouseEvent,)>` closure, found `yew::Callback<String>`
|
error[E0277]: expected a `Fn<(MouseEvent,)>` closure, found `yew::Callback<String>`
|
||||||
@ -682,7 +649,7 @@ error[E0277]: the trait bound `NotToString: IntoPropValue<Option<implicit_clone:
|
|||||||
<&'static str as IntoPropValue<Option<implicit_clone::unsync::IString>>>
|
<&'static str as IntoPropValue<Option<implicit_clone::unsync::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::IString>>
|
||||||
<&T as IntoPropValue<Option<T>>>
|
<&String as IntoPropValue<VNode>>
|
||||||
and $N others
|
and $N others
|
||||||
|
|
||||||
error[E0277]: the trait bound `(): IntoPropValue<yew::NodeRef>` is not satisfied
|
error[E0277]: the trait bound `(): IntoPropValue<yew::NodeRef>` is not satisfied
|
||||||
@ -691,16 +658,7 @@ error[E0277]: the trait bound `(): IntoPropValue<yew::NodeRef>` is not satisfied
|
|||||||
62 | html! { <input ref={()} /> };
|
62 | html! { <input ref={()} /> };
|
||||||
| ^^ the trait `IntoPropValue<yew::NodeRef>` is not implemented for `()`
|
| ^^ the trait `IntoPropValue<yew::NodeRef>` is not implemented for `()`
|
||||||
|
|
|
|
||||||
= help: the following other types implement trait `IntoPropValue<T>`:
|
= help: the trait `IntoPropValue<VNode>` is implemented for `()`
|
||||||
<&'static [(K, V)] as IntoPropValue<implicit_clone::unsync::IMap<K, V>>>
|
|
||||||
<&'static [T] as IntoPropValue<implicit_clone::unsync::IArray<T>>>
|
|
||||||
<&'static str as IntoPropValue<Classes>>
|
|
||||||
<&'static str as IntoPropValue<Option<String>>>
|
|
||||||
<&'static str as IntoPropValue<Option<implicit_clone::unsync::IString>>>
|
|
||||||
<&'static str as IntoPropValue<String>>
|
|
||||||
<&'static str as IntoPropValue<implicit_clone::unsync::IString>>
|
|
||||||
<&T as IntoPropValue<Option<T>>>
|
|
||||||
and $N others
|
|
||||||
= 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::IString: From<{integer}>` is not satisfied
|
||||||
|
|||||||
@ -193,10 +193,11 @@ where
|
|||||||
/// ```
|
/// ```
|
||||||
/// # let children = Children::new(Vec::new());
|
/// # let children = Children::new(Vec::new());
|
||||||
/// # use yew::{classes, html, Children};
|
/// # use yew::{classes, html, Children};
|
||||||
|
/// # let _ =
|
||||||
/// children.map(|children| {
|
/// children.map(|children| {
|
||||||
/// html! {
|
/// html! {
|
||||||
/// <div class={classes!("container")}>
|
/// <div class={classes!("container")}>
|
||||||
/// {children}
|
/// {children.clone()}
|
||||||
/// </div>
|
/// </div>
|
||||||
/// }
|
/// }
|
||||||
/// })
|
/// })
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use implicit_clone::unsync::{IArray, IMap};
|
use implicit_clone::unsync::{IArray, IMap};
|
||||||
pub use implicit_clone::ImplicitClone;
|
pub use implicit_clone::ImplicitClone;
|
||||||
|
|
||||||
use super::ToHtml;
|
|
||||||
use crate::callback::Callback;
|
use crate::callback::Callback;
|
||||||
use crate::html::{BaseComponent, ChildrenRenderer, Component, NodeRef, Scope};
|
use crate::html::{BaseComponent, ChildrenRenderer, Component, NodeRef, Scope};
|
||||||
use crate::virtual_dom::{AttrValue, VChild, VList, VNode, VText};
|
use crate::virtual_dom::{AttrValue, VChild, VList, VNode, VText};
|
||||||
@ -130,13 +130,40 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> IntoPropValue<VNode> for T
|
impl<T> IntoPropValue<VNode> for VChild<T>
|
||||||
where
|
where
|
||||||
T: ToHtml,
|
T: BaseComponent,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_prop_value(self) -> VNode {
|
fn into_prop_value(self) -> VNode {
|
||||||
self.into_html()
|
VNode::from(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoPropValue<VNode> for VList {
|
||||||
|
#[inline]
|
||||||
|
fn into_prop_value(self) -> VNode {
|
||||||
|
VNode::VList(Rc::new(self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl IntoPropValue<VNode> for VText {
|
||||||
|
#[inline]
|
||||||
|
fn into_prop_value(self) -> VNode {
|
||||||
|
VNode::VText(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoPropValue<VNode> for () {
|
||||||
|
#[inline]
|
||||||
|
fn into_prop_value(self) -> VNode {
|
||||||
|
VNode::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoPropValue<VNode> for ChildrenRenderer<VNode> {
|
||||||
|
#[inline]
|
||||||
|
fn into_prop_value(self) -> VNode {
|
||||||
|
VNode::VList(Rc::new(self.into()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,6 +195,26 @@ impl<C: BaseComponent> IntoPropValue<VList> for VChild<C> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl IntoPropValue<ChildrenRenderer<VNode>> for AttrValue {
|
||||||
|
fn into_prop_value(self) -> ChildrenRenderer<VNode> {
|
||||||
|
ChildrenRenderer::new(vec![VNode::VText(VText::new(self))])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoPropValue<VNode> for Vec<VNode> {
|
||||||
|
#[inline]
|
||||||
|
fn into_prop_value(self) -> VNode {
|
||||||
|
VNode::VList(Rc::new(VList::with_children(self, None)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoPropValue<VNode> for Option<VNode> {
|
||||||
|
#[inline]
|
||||||
|
fn into_prop_value(self) -> VNode {
|
||||||
|
self.unwrap_or_default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! impl_into_prop {
|
macro_rules! impl_into_prop {
|
||||||
(|$value:ident: $from_ty:ty| -> $to_ty:ty { $conversion:expr }) => {
|
(|$value:ident: $from_ty:ty| -> $to_ty:ty { $conversion:expr }) => {
|
||||||
// implement V -> T
|
// implement V -> T
|
||||||
@ -231,6 +278,57 @@ impl<K: Eq + std::hash::Hash + ImplicitClone + 'static, V: PartialEq + ImplicitC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_into_prop_value_via_display {
|
||||||
|
($from_ty: ty) => {
|
||||||
|
impl IntoPropValue<VNode> for $from_ty {
|
||||||
|
#[inline(always)]
|
||||||
|
fn into_prop_value(self) -> VNode {
|
||||||
|
VText::from(self).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// go through AttrValue::from where possible
|
||||||
|
macro_rules! impl_into_prop_value_via_attr_value {
|
||||||
|
($from_ty: ty) => {
|
||||||
|
impl IntoPropValue<VNode> for $from_ty {
|
||||||
|
#[inline(always)]
|
||||||
|
fn into_prop_value(self) -> VNode {
|
||||||
|
VText::new(self).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// These are a selection of types implemented via display.
|
||||||
|
impl_into_prop_value_via_display!(bool);
|
||||||
|
impl_into_prop_value_via_display!(char);
|
||||||
|
impl_into_prop_value_via_display!(&String);
|
||||||
|
impl_into_prop_value_via_display!(&str);
|
||||||
|
impl_into_prop_value_via_display!(Arc<str>);
|
||||||
|
impl_into_prop_value_via_display!(Arc<String>);
|
||||||
|
impl_into_prop_value_via_display!(Rc<String>);
|
||||||
|
impl_into_prop_value_via_display!(u8);
|
||||||
|
impl_into_prop_value_via_display!(u16);
|
||||||
|
impl_into_prop_value_via_display!(u32);
|
||||||
|
impl_into_prop_value_via_display!(u64);
|
||||||
|
impl_into_prop_value_via_display!(u128);
|
||||||
|
impl_into_prop_value_via_display!(usize);
|
||||||
|
impl_into_prop_value_via_display!(i8);
|
||||||
|
impl_into_prop_value_via_display!(i16);
|
||||||
|
impl_into_prop_value_via_display!(i32);
|
||||||
|
impl_into_prop_value_via_display!(i64);
|
||||||
|
impl_into_prop_value_via_display!(i128);
|
||||||
|
impl_into_prop_value_via_display!(isize);
|
||||||
|
impl_into_prop_value_via_display!(f32);
|
||||||
|
impl_into_prop_value_via_display!(f64);
|
||||||
|
|
||||||
|
impl_into_prop_value_via_attr_value!(String);
|
||||||
|
impl_into_prop_value_via_attr_value!(AttrValue);
|
||||||
|
impl_into_prop_value_via_attr_value!(Rc<str>);
|
||||||
|
impl_into_prop_value_via_attr_value!(Cow<'static, str>);
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -408,4 +506,30 @@ mod test {
|
|||||||
</Parent>
|
</Parent>
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn attr_value_children() {
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
#[derive(PartialEq, Properties)]
|
||||||
|
pub struct ChildProps {
|
||||||
|
#[prop_or_default]
|
||||||
|
pub children: AttrValue,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[function_component]
|
||||||
|
fn Child(_props: &ChildProps) -> Html {
|
||||||
|
html!()
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let attr_value = AttrValue::from("foo");
|
||||||
|
|
||||||
|
let _ = html! { <Child>{attr_value}</Child> };
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let attr_value = AttrValue::from("foo");
|
||||||
|
|
||||||
|
let _ = html! { <Child>{&attr_value}</Child> };
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,2 @@
|
|||||||
mod into_prop_value;
|
mod into_prop_value;
|
||||||
mod to_html;
|
|
||||||
|
|
||||||
pub use into_prop_value::*;
|
pub use into_prop_value::*;
|
||||||
pub use to_html::*;
|
|
||||||
|
|||||||
@ -1,203 +0,0 @@
|
|||||||
use std::borrow::Cow;
|
|
||||||
use std::rc::Rc;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use crate::html::{ChildrenRenderer, IntoPropValue};
|
|
||||||
use crate::virtual_dom::{VChild, VList, VNode, VText};
|
|
||||||
use crate::{AttrValue, BaseComponent, Html};
|
|
||||||
|
|
||||||
/// A trait implemented for types be rendered as a part of a Html.
|
|
||||||
///
|
|
||||||
/// Types that implements this trait can define a virtual dom layout that itself should be rendered
|
|
||||||
/// into via `html!` and can be referenced / consumed as `{value}` in an `html!` macro invocation.
|
|
||||||
pub trait ToHtml {
|
|
||||||
/// Converts this type to a [`Html`].
|
|
||||||
fn to_html(&self) -> Html;
|
|
||||||
|
|
||||||
/// Converts this type into a [`Html`].
|
|
||||||
fn into_html(self) -> Html
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.to_html()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implementations for common data types.
|
|
||||||
|
|
||||||
impl<T> ToHtml for Option<T>
|
|
||||||
where
|
|
||||||
T: ToHtml,
|
|
||||||
{
|
|
||||||
#[inline(always)]
|
|
||||||
fn to_html(&self) -> Html {
|
|
||||||
self.as_ref().map(ToHtml::to_html).unwrap_or_default()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn into_html(self) -> Html {
|
|
||||||
self.map(ToHtml::into_html).unwrap_or_default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> ToHtml for Vec<T>
|
|
||||||
where
|
|
||||||
T: ToHtml,
|
|
||||||
{
|
|
||||||
#[inline(always)]
|
|
||||||
fn to_html(&self) -> Html {
|
|
||||||
Html::VList(Rc::new(VList::with_children(
|
|
||||||
self.iter().map(ToHtml::to_html).collect(),
|
|
||||||
None,
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn into_html(self) -> Html {
|
|
||||||
Html::VList(Rc::new(VList::with_children(
|
|
||||||
self.into_iter().map(ToHtml::into_html).collect(),
|
|
||||||
None,
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToHtml for Option<VNode> {
|
|
||||||
#[inline(always)]
|
|
||||||
fn to_html(&self) -> Html {
|
|
||||||
self.clone().into_html()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn into_html(self) -> Html {
|
|
||||||
self.unwrap_or_default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToHtml for Vec<VNode> {
|
|
||||||
#[inline(always)]
|
|
||||||
fn to_html(&self) -> Html {
|
|
||||||
self.clone().into_html()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn into_html(self) -> Html {
|
|
||||||
Html::VList(Rc::new(VList::with_children(self, None)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToHtml for VText {
|
|
||||||
#[inline(always)]
|
|
||||||
fn to_html(&self) -> Html {
|
|
||||||
self.clone().into()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn into_html(self) -> Html {
|
|
||||||
Html::VText(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToHtml for VList {
|
|
||||||
#[inline(always)]
|
|
||||||
fn to_html(&self) -> Html {
|
|
||||||
self.clone().into()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn into_html(self) -> Html {
|
|
||||||
Html::VList(Rc::new(self))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToHtml for ChildrenRenderer<VNode> {
|
|
||||||
#[inline(always)]
|
|
||||||
fn to_html(&self) -> Html {
|
|
||||||
self.clone().into()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn into_html(self) -> Html {
|
|
||||||
self.into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> ToHtml for VChild<T>
|
|
||||||
where
|
|
||||||
T: BaseComponent,
|
|
||||||
{
|
|
||||||
#[inline(always)]
|
|
||||||
fn to_html(&self) -> Html {
|
|
||||||
self.clone().into()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn into_html(self) -> Html {
|
|
||||||
VNode::VComp(Rc::new(self.into()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToHtml for () {
|
|
||||||
#[inline(always)]
|
|
||||||
fn to_html(&self) -> Html {
|
|
||||||
VNode::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn into_html(self) -> Html {
|
|
||||||
VNode::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> ToHtml for &'_ T
|
|
||||||
where
|
|
||||||
T: ToHtml,
|
|
||||||
{
|
|
||||||
fn to_html(&self) -> Html {
|
|
||||||
(*self).to_html()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_to_html_via_display {
|
|
||||||
($from_ty: ty) => {
|
|
||||||
impl ToHtml for $from_ty {
|
|
||||||
#[inline(always)]
|
|
||||||
fn to_html(&self) -> Html {
|
|
||||||
Html::VText(VText::from(self))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mirror ToHtml to Children implementation.
|
|
||||||
impl IntoPropValue<ChildrenRenderer<VNode>> for $from_ty {
|
|
||||||
#[inline(always)]
|
|
||||||
fn into_prop_value(self) -> ChildrenRenderer<VNode> {
|
|
||||||
ChildrenRenderer::new(vec![VText::from(self).into()])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// These are a selection of types implemented via display.
|
|
||||||
impl_to_html_via_display!(bool);
|
|
||||||
impl_to_html_via_display!(char);
|
|
||||||
impl_to_html_via_display!(String);
|
|
||||||
impl_to_html_via_display!(&str);
|
|
||||||
impl_to_html_via_display!(Rc<str>);
|
|
||||||
impl_to_html_via_display!(Rc<String>);
|
|
||||||
impl_to_html_via_display!(Arc<str>);
|
|
||||||
impl_to_html_via_display!(Arc<String>);
|
|
||||||
impl_to_html_via_display!(AttrValue);
|
|
||||||
impl_to_html_via_display!(Cow<'_, str>);
|
|
||||||
impl_to_html_via_display!(u8);
|
|
||||||
impl_to_html_via_display!(u16);
|
|
||||||
impl_to_html_via_display!(u32);
|
|
||||||
impl_to_html_via_display!(u64);
|
|
||||||
impl_to_html_via_display!(u128);
|
|
||||||
impl_to_html_via_display!(usize);
|
|
||||||
impl_to_html_via_display!(i8);
|
|
||||||
impl_to_html_via_display!(i16);
|
|
||||||
impl_to_html_via_display!(i32);
|
|
||||||
impl_to_html_via_display!(i64);
|
|
||||||
impl_to_html_via_display!(i128);
|
|
||||||
impl_to_html_via_display!(isize);
|
|
||||||
impl_to_html_via_display!(f32);
|
|
||||||
impl_to_html_via_display!(f64);
|
|
||||||
@ -336,7 +336,7 @@ pub mod prelude {
|
|||||||
pub use crate::functional::*;
|
pub use crate::functional::*;
|
||||||
pub use crate::html::{
|
pub use crate::html::{
|
||||||
create_portal, BaseComponent, Children, ChildrenWithProps, Classes, Component, Context,
|
create_portal, BaseComponent, Children, ChildrenWithProps, Classes, Component, Context,
|
||||||
Html, HtmlResult, NodeRef, Properties, ToHtml,
|
Html, HtmlResult, NodeRef, Properties,
|
||||||
};
|
};
|
||||||
pub use crate::macros::{classes, html, html_nested};
|
pub use crate::macros::{classes, html, html_nested};
|
||||||
pub use crate::suspense::Suspense;
|
pub use crate::suspense::Suspense;
|
||||||
|
|||||||
@ -183,6 +183,8 @@ pub struct VChild<COMP: BaseComponent> {
|
|||||||
key: Option<Key>,
|
key: Option<Key>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<COMP: BaseComponent> implicit_clone::ImplicitClone for VChild<COMP> {}
|
||||||
|
|
||||||
impl<COMP: BaseComponent> Clone for VChild<COMP> {
|
impl<COMP: BaseComponent> Clone for VChild<COMP> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
VChild {
|
VChild {
|
||||||
|
|||||||
@ -10,7 +10,7 @@ The `#[function_component]` attribute also works with generic functions for crea
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use yew::{function_component, html, Properties, Html, ToHtml};
|
use yew::{function_component, html, Properties, Html};
|
||||||
|
|
||||||
#[derive(Properties, PartialEq)]
|
#[derive(Properties, PartialEq)]
|
||||||
pub struct Props<T>
|
pub struct Props<T>
|
||||||
@ -23,11 +23,11 @@ where
|
|||||||
#[function_component]
|
#[function_component]
|
||||||
pub fn MyGenericComponent<T>(props: &Props<T>) -> Html
|
pub fn MyGenericComponent<T>(props: &Props<T>) -> Html
|
||||||
where
|
where
|
||||||
T: PartialEq + ToHtml,
|
T: PartialEq + Clone + Into<Html>,
|
||||||
{
|
{
|
||||||
html! {
|
html! {
|
||||||
<p>
|
<p>
|
||||||
{ &props.data }
|
{ props.data.clone().into() }
|
||||||
</p>
|
</p>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user