diff --git a/README.md b/README.md index 0805076d8..3600b2238 100644 --- a/README.md +++ b/README.md @@ -240,7 +240,7 @@ Properties are also pure Rust types with strict type-checking during the compila ```rust // my_button.rs -#[derive(Properties, PartialEq)] +#[derive(Clone, Properties, PartialEq)] pub struct Properties { pub hidden: bool, #[props(required)] diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index bf09cc502..ba556e008 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -119,16 +119,9 @@ impl ToTokens for HtmlComponent { }; let set_children = if !children.is_empty() { - let children_len = children.len(); quote! { .children(::yew::html::ChildrenRenderer::new( - #children_len, - ::std::boxed::Box::new(move || { - #[allow(unused_must_use)] - || -> ::std::vec::Vec<_> { - vec![#(#children.into(),)*] - } - }()), + vec![#(#children.into(),)*] )) } } else { diff --git a/crates/macro/src/html_tree/html_tag/mod.rs b/crates/macro/src/html_tree/html_tag/mod.rs index b6ba8d1d2..727e947ea 100644 --- a/crates/macro/src/html_tree/html_tag/mod.rs +++ b/crates/macro/src/html_tree/html_tag/mod.rs @@ -172,7 +172,7 @@ impl ToTokens for HtmlTag { #(#set_classes)* #(#set_node_ref)* #vtag.add_attributes(vec![#(#attr_pairs),*]); - #vtag.add_listeners(vec![#(::std::boxed::Box::new(#listeners)),*]); + #vtag.add_listeners(vec![#(::std::rc::Rc::new(#listeners)),*]); #vtag.add_children(vec![#(#children),*]); ::yew::virtual_dom::VNode::from(#vtag) }}); diff --git a/crates/macro/src/lib.rs b/crates/macro/src/lib.rs index f6216c62f..1dcfee433 100644 --- a/crates/macro/src/lib.rs +++ b/crates/macro/src/lib.rs @@ -13,7 +13,7 @@ //! link: ComponentLink, //! } //! -//! #[derive(Properties)] +//! #[derive(Clone, Properties)] //! struct Props { //! #[props(required)] //! prop: String, diff --git a/examples/custom_components/src/barrier.rs b/examples/custom_components/src/barrier.rs index 8653c7401..bd85c923c 100644 --- a/examples/custom_components/src/barrier.rs +++ b/examples/custom_components/src/barrier.rs @@ -12,7 +12,7 @@ pub enum Msg { ChildClicked, } -#[derive(PartialEq, Properties)] +#[derive(Clone, PartialEq, Properties)] pub struct Props { pub limit: u32, #[props(required)] diff --git a/examples/custom_components/src/button.rs b/examples/custom_components/src/button.rs index 548b164c6..39047d048 100644 --- a/examples/custom_components/src/button.rs +++ b/examples/custom_components/src/button.rs @@ -10,7 +10,7 @@ pub enum Msg { Clicked, } -#[derive(PartialEq, Properties)] +#[derive(Clone, PartialEq, Properties)] pub struct Props { pub title: String, #[props(required)] diff --git a/examples/custom_components/src/counter.rs b/examples/custom_components/src/counter.rs index 5d5c186ef..610e56abf 100644 --- a/examples/custom_components/src/counter.rs +++ b/examples/custom_components/src/counter.rs @@ -24,7 +24,7 @@ pub enum Msg { Increase, } -#[derive(PartialEq, Properties)] +#[derive(Clone, PartialEq, Properties)] pub struct Props { pub initial: u32, pub color: Color, diff --git a/examples/nested_list/Cargo.toml b/examples/nested_list/Cargo.toml index aefc4ba6a..744148fd5 100644 --- a/examples/nested_list/Cargo.toml +++ b/examples/nested_list/Cargo.toml @@ -5,4 +5,6 @@ authors = ["Justin Starry "] edition = "2018" [dependencies] +log = "0.4" +web_logger = "0.2" yew = { path = "../.." } diff --git a/examples/nested_list/src/app.rs b/examples/nested_list/src/app.rs new file mode 100644 index 000000000..8e1d022a3 --- /dev/null +++ b/examples/nested_list/src/app.rs @@ -0,0 +1,77 @@ +use super::header::ListHeader; +use super::item::ListItem; +use super::list::List; +use super::{Hovered, WeakComponentLink}; +use yew::prelude::*; + +pub struct App { + link: ComponentLink, + hovered: Hovered, +} + +pub enum Msg { + Hover(Hovered), +} + +impl Component for App { + type Message = Msg; + type Properties = (); + + fn create(_: Self::Properties, link: ComponentLink) -> Self { + App { + link, + hovered: Hovered::None, + } + } + + fn update(&mut self, msg: Self::Message) -> ShouldRender { + match msg { + Msg::Hover(hovered) => self.hovered = hovered, + } + true + } + + fn view(&self) -> Html { + let on_hover = &self.link.callback(Msg::Hover); + let onmouseenter = &self.link.callback(|_| Msg::Hover(Hovered::None)); + let list_link = &WeakComponentLink::::default(); + let sub_list_link = &WeakComponentLink::::default(); + html! { +
+

{ "Nested List Demo" }

+ + + + + +
{"Sublist!"}
+ { + html! { + + + + + + + } + } +
+
+ {self.view_last_hovered()} +
+ } + } +} + +impl App { + fn view_last_hovered(&self) -> Html { + html! { +
+ { "Last hovered:"} + + { &self.hovered } + +
+ } + } +} diff --git a/examples/nested_list/src/header.rs b/examples/nested_list/src/header.rs index a7c313044..995d235f2 100644 --- a/examples/nested_list/src/header.rs +++ b/examples/nested_list/src/header.rs @@ -1,16 +1,19 @@ -use crate::Hovered; +use super::list::{List, Msg as ListMsg}; +use super::{Hovered, WeakComponentLink}; use yew::prelude::*; pub struct ListHeader { props: Props, } -#[derive(Properties)] +#[derive(Clone, Properties)] pub struct Props { #[props(required)] pub on_hover: Callback, #[props(required)] pub text: String, + #[props(required)] + pub list_link: WeakComponentLink, } impl Component for ListHeader { @@ -26,9 +29,11 @@ impl Component for ListHeader { } fn view(&self) -> Html { + let list_link = self.props.list_link.borrow().clone().unwrap(); + let onclick = list_link.callback(|_| ListMsg::HeaderClick); let onmouseover = self.props.on_hover.reform(|_| Hovered::Header); html! { -
+
{ &self.props.text }
} diff --git a/examples/nested_list/src/item.rs b/examples/nested_list/src/item.rs index 456256d97..e82994746 100644 --- a/examples/nested_list/src/item.rs +++ b/examples/nested_list/src/item.rs @@ -6,7 +6,7 @@ pub struct ListItem { props: Props, } -#[derive(Properties)] +#[derive(Clone, Properties)] pub struct Props { pub hide: bool, #[props(required)] @@ -30,7 +30,10 @@ impl Component for ListItem { fn view(&self) -> Html { let name = self.props.name.clone(); - let onmouseover = self.props.on_hover.reform(move |_| Hovered::Item(name.clone())); + let onmouseover = self + .props + .on_hover + .reform(move |_| Hovered::Item(name.clone())); html! {
{ &self.props.name } diff --git a/examples/nested_list/src/lib.rs b/examples/nested_list/src/lib.rs index 00323f674..71c486823 100644 --- a/examples/nested_list/src/lib.rs +++ b/examples/nested_list/src/lib.rs @@ -1,19 +1,16 @@ -#![recursion_limit = "128"] +#![recursion_limit = "512"] +mod app; mod header; mod item; mod list; -use header::ListHeader; -use item::ListItem; -use list::List; -use yew::prelude::*; +pub use app::App; +use std::cell::RefCell; use std::fmt; - -pub struct Model { - link: ComponentLink, - hovered: Hovered, -} +use std::rc::Rc; +use yew::html::ComponentLink; +pub type WeakComponentLink = Rc>>>; #[derive(Debug)] pub enum Hovered { @@ -23,60 +20,6 @@ pub enum Hovered { None, } -pub enum Msg { - Hover(Hovered), -} - -impl Component for Model { - type Message = Msg; - type Properties = (); - - fn create(_: Self::Properties, link: ComponentLink) -> Self { - Model { link, - hovered: Hovered::None, - } - } - - fn update(&mut self, msg: Self::Message) -> ShouldRender { - match msg { - Msg::Hover(hovered) => self.hovered = hovered, - } - true - } - - fn view(&self) -> Html { - let on_hover = self.link.callback(Msg::Hover); - - html! { -
-

{ "Nested List Demo" }

- - - - - - {"Hello!"} - - - {self.view_last_hovered()} -
- } - } -} - -impl Model { - fn view_last_hovered(&self) -> Html { - html! { -
- { "Last hovered:"} - - { &self.hovered } - -
- } - } -} - impl fmt::Display for Hovered { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( diff --git a/examples/nested_list/src/list.rs b/examples/nested_list/src/list.rs index c30348831..1b0faa3ef 100644 --- a/examples/nested_list/src/list.rs +++ b/examples/nested_list/src/list.rs @@ -1,10 +1,11 @@ -use crate::{header::Props as HeaderProps, ListHeader}; -use crate::{item::Props as ItemProps, ListItem}; -use crate::Hovered; +use super::{Hovered, WeakComponentLink}; +use crate::{header::ListHeader, header::Props as HeaderProps}; +use crate::{item::ListItem, item::Props as ItemProps}; use yew::html::{ChildrenRenderer, NodeRef}; use yew::prelude::*; use yew::virtual_dom::{VChild, VComp, VNode}; +#[derive(Clone)] pub enum Variants { Item(::Properties), Header(::Properties), @@ -22,40 +23,58 @@ impl From for Variants { } } +#[derive(Clone)] pub struct ListVariant { props: Variants, } -#[derive(Properties)] +#[derive(Clone, Properties)] pub struct Props { #[props(required)] pub children: ChildrenRenderer, #[props(required)] pub on_hover: Callback, + #[props(required)] + pub weak_link: WeakComponentLink, } pub struct List { props: Props, + inactive: bool, +} + +pub enum Msg { + HeaderClick, } impl Component for List { - type Message = (); + type Message = Msg; type Properties = Props; - fn create(props: Self::Properties, _: ComponentLink) -> Self { - List { props } + fn create(props: Self::Properties, link: ComponentLink) -> Self { + *props.weak_link.borrow_mut() = Some(link); + List { + props, + inactive: false, + } } - fn update(&mut self, _msg: Self::Message) -> ShouldRender { - false + fn update(&mut self, msg: Self::Message) -> ShouldRender { + match msg { + Msg::HeaderClick => { + self.inactive = !self.inactive; + true + } + } } fn view(&self) -> Html { + let inactive = if self.inactive { "inactive" } else { "" }; let onmouseover = self.props.on_hover.reform(|_| Hovered::List); let onmouseout = self.props.on_hover.reform(|_| Hovered::None); html! {
-
+
{self.view_header()}
{self.view_items()} diff --git a/examples/nested_list/src/main.rs b/examples/nested_list/src/main.rs index 9dab1b827..130defbc4 100644 --- a/examples/nested_list/src/main.rs +++ b/examples/nested_list/src/main.rs @@ -1,3 +1,4 @@ fn main() { - yew::start_app::(); + web_logger::init(); + yew::start_app::(); } diff --git a/examples/nested_list/static/styles.css b/examples/nested_list/static/styles.css index 51b72cc14..79b3ca905 100644 --- a/examples/nested_list/static/styles.css +++ b/examples/nested_list/static/styles.css @@ -35,10 +35,15 @@ html, body { min-width: 30vw; } +.list.inactive { + opacity: 0.5; +} + .list-header { background: #FEECAA; border-bottom: 1px solid #666; padding: 10px; + cursor: pointer; } .list-header:hover { @@ -65,6 +70,7 @@ html, body { border-radius: 3px; margin-top: 10px; padding: 10px; + text-align: center; } .last-hovered { @@ -75,3 +81,17 @@ html, body { color: #666; margin-left: 5px; } + +.list-item-details .list-container { + margin-top: 0px; + padding: 15px; +} + +.sublist { + display: inline-block; + background: #FFF; + border: 1px solid #666; + border-radius: 3px; + margin: 5px; + padding: 5px 20px; +} diff --git a/examples/node_refs/src/input.rs b/examples/node_refs/src/input.rs index 6a3931eae..e26f27c4a 100644 --- a/examples/node_refs/src/input.rs +++ b/examples/node_refs/src/input.rs @@ -5,7 +5,7 @@ pub struct InputComponent { link: ComponentLink, } -#[derive(Properties)] +#[derive(Clone, Properties)] pub struct Props { #[props(required)] pub on_hover: Callback<()>, diff --git a/src/html/mod.rs b/src/html/mod.rs index 4eb4b0d61..b567846b4 100644 --- a/src/html/mod.rs +++ b/src/html/mod.rs @@ -64,7 +64,7 @@ pub type Html = VNode; /// In this example, the `Wrapper` component is used to wrap other elements. /// ``` ///# use yew::{Children, Html, Properties, Component, ComponentLink, html}; -///# #[derive(Properties)] +///# #[derive(Clone, Properties)] ///# struct WrapperProps { ///# children: Children, ///# } @@ -92,7 +92,7 @@ pub type Html = VNode; /// children property can be used to render the wrapped elements. /// ``` ///# use yew::{Children, Html, Properties, Renderable, Component, ComponentLink, html}; -/// #[derive(Properties)] +/// #[derive(Clone, Properties)] /// struct WrapperProps { /// children: Children, /// } @@ -124,7 +124,7 @@ pub type Children = ChildrenRenderer; /// ``` ///# use yew::{html, Component, Renderable, Html, ComponentLink, ChildrenWithProps, Properties}; ///# -///# #[derive(Properties)] +///# #[derive(Clone, Properties)] ///# struct ListProps { ///# children: ChildrenWithProps, ///# } @@ -136,7 +136,7 @@ pub type Children = ChildrenRenderer; ///# fn update(&mut self, msg: Self::Message) -> bool {unimplemented!()} ///# fn view(&self) -> Html {unimplemented!()} ///# } -///# #[derive(Properties)] +///# #[derive(Clone, Properties)] ///# struct ListItemProps { ///# value: String ///# } @@ -166,7 +166,7 @@ pub type Children = ChildrenRenderer; /// ``` ///# use yew::{html, Component, Html, ChildrenWithProps, ComponentLink, Properties}; ///# -/// #[derive(Properties)] +/// #[derive(Clone, Properties)] /// struct ListProps { /// children: ChildrenWithProps, /// } @@ -188,7 +188,7 @@ pub type Children = ChildrenRenderer; /// } /// } ///# -///# #[derive(Properties)] +///# #[derive(Clone, Properties)] ///# struct ListItemProps { ///# value: String ///# } @@ -205,30 +205,33 @@ pub type Children = ChildrenRenderer; pub type ChildrenWithProps = ChildrenRenderer>; /// A type used for rendering children html. +#[derive(Clone)] pub struct ChildrenRenderer { - len: usize, - boxed_render: Box Vec>, + children: Vec, } -impl ChildrenRenderer { +impl ChildrenRenderer +where + T: Clone + Into, +{ /// Create children - pub fn new(len: usize, boxed_render: Box Vec>) -> Self { - Self { len, boxed_render } + pub fn new(children: Vec) -> Self { + Self { children } } /// Children list is empty pub fn is_empty(&self) -> bool { - self.len == 0 + self.children.is_empty() } /// Number of children elements pub fn len(&self) -> usize { - self.len + self.children.len() } /// Build children components and return `Vec` pub fn to_vec(&self) -> Vec { - (&self.boxed_render)() + self.children.clone() } /// Render children components and return `Iterator` @@ -239,13 +242,8 @@ impl ChildrenRenderer { impl Default for ChildrenRenderer { fn default() -> Self { - // False positive: https://github.com/rust-lang/rust-clippy/issues/4002 - #[allow(clippy::redundant_closure)] - let boxed_render = Box::new(|| Vec::new()); - Self { - len: 0, - boxed_render, + children: Vec::new(), } } } @@ -258,7 +256,7 @@ impl fmt::Debug for ChildrenRenderer { impl Renderable for ChildrenRenderer where - T: Into, + T: Clone + Into, { fn render(&self) -> Html { VList::new_with_children(self.iter().map(|c| c.into()).collect()).into() @@ -338,7 +336,7 @@ impl Renderable for COMP { } /// Trait for building properties for a component -pub trait Properties { +pub trait Properties: Clone { /// Builder that will be used to construct properties type Builder; diff --git a/src/virtual_dom/mod.rs b/src/virtual_dom/mod.rs index 4d12eb2eb..f1b32c6ef 100644 --- a/src/virtual_dom/mod.rs +++ b/src/virtual_dom/mod.rs @@ -9,6 +9,7 @@ pub mod vtext; use indexmap::set::IndexSet; use std::collections::HashMap; use std::fmt; +use std::rc::Rc; use stdweb::web::{Element, EventListenerHandle, Node}; pub use self::vcomp::{VChild, VComp}; @@ -33,7 +34,7 @@ impl fmt::Debug for dyn Listener { } /// A list of event listeners. -type Listeners = Vec>; +type Listeners = Vec>; /// A map of attributes. type Attributes = HashMap; diff --git a/src/virtual_dom/vcomp.rs b/src/virtual_dom/vcomp.rs index 67ecdade8..bd533fa1a 100644 --- a/src/virtual_dom/vcomp.rs +++ b/src/virtual_dom/vcomp.rs @@ -9,7 +9,7 @@ use std::rc::Rc; use stdweb::web::{document, Element, INode, Node, TextNode}; /// The method generates an instance of a component. -type Generator = dyn FnOnce(GeneratorType) -> Mounted; +type Generator = dyn Fn(GeneratorType) -> Mounted; /// Components can be generated by mounting or by overwriting an old component. enum GeneratorType { @@ -23,6 +23,15 @@ pub struct VComp { state: Rc>, } +impl Clone for VComp { + fn clone(&self) -> Self { + VComp { + type_id: self.type_id, + state: self.state.clone(), + } + } +} + /// A virtual child component. pub struct VChild { /// The component properties @@ -31,6 +40,15 @@ pub struct VChild { node_ref: NodeRef, } +impl Clone for VChild { + fn clone(&self) -> Self { + VChild { + props: self.props.clone(), + node_ref: self.node_ref.clone(), + } + } +} + impl VChild where COMP: Component, @@ -83,21 +101,21 @@ impl VComp { element, Some(VNode::VRef(dummy_node.into())), node_ref.clone(), - props, + props.clone(), ); Mounted { - node_ref, + node_ref: node_ref.clone(), scope: scope.clone().into(), destroyer: Box::new(move || scope.destroy()), } } GeneratorType::Overwrite(hidden_scope) => { let mut scope: Scope = hidden_scope.into(); - scope.update(ComponentUpdate::Properties(props)); + scope.update(ComponentUpdate::Properties(props.clone())); Mounted { - node_ref, + node_ref: node_ref.clone(), scope: scope.clone().into(), destroyer: Box::new(move || scope.destroy()), } diff --git a/src/virtual_dom/vlist.rs b/src/virtual_dom/vlist.rs index 43cc00537..5748d4a1b 100644 --- a/src/virtual_dom/vlist.rs +++ b/src/virtual_dom/vlist.rs @@ -4,7 +4,7 @@ use std::ops::{Deref, DerefMut}; use stdweb::web::{Element, Node}; /// This struct represents a fragment of the Virtual DOM tree. -#[derive(Debug, PartialEq, Default)] +#[derive(Clone, Debug, PartialEq, Default)] pub struct VList { /// The list of children nodes. pub children: Vec, diff --git a/src/virtual_dom/vnode.rs b/src/virtual_dom/vnode.rs index fef26f562..3e0eed744 100644 --- a/src/virtual_dom/vnode.rs +++ b/src/virtual_dom/vnode.rs @@ -8,6 +8,7 @@ use std::iter::FromIterator; use stdweb::web::{Element, INode, Node}; /// Bind virtual element to a DOM reference. +#[derive(Clone)] pub enum VNode { /// A bind between `VTag` and `Element`. VTag(Box), diff --git a/src/virtual_dom/vtag.rs b/src/virtual_dom/vtag.rs index 53924842b..bc24831fd 100644 --- a/src/virtual_dom/vtag.rs +++ b/src/virtual_dom/vtag.rs @@ -8,6 +8,7 @@ use log::warn; use std::borrow::Cow; use std::cmp::PartialEq; use std::fmt; +use std::rc::Rc; use stdweb::unstable::TryFrom; use stdweb::web::html_element::InputElement; use stdweb::web::html_element::TextAreaElement; @@ -56,6 +57,24 @@ pub struct VTag { captured: Vec, } +impl Clone for VTag { + fn clone(&self) -> Self { + VTag { + tag: self.tag.clone(), + reference: None, + listeners: self.listeners.clone(), + attributes: self.attributes.clone(), + children: self.children.clone(), + classes: self.classes.clone(), + value: self.value.clone(), + kind: self.kind.clone(), + checked: self.checked, + node_ref: self.node_ref.clone(), + captured: Vec::new(), + } + } +} + impl VTag { /// Creates a new `VTag` instance with `tag` name (cannot be changed later in DOM). pub fn new>>(tag: S) -> Self { @@ -161,14 +180,14 @@ impl VTag { /// Adds new listener to the node. /// It's boxed because we want to keep it in a single list. /// Later `Listener::attach` will attach an actual listener to a DOM node. - pub fn add_listener(&mut self, listener: Box) { + pub fn add_listener(&mut self, listener: Rc) { self.listeners.push(listener); } /// Adds new listeners to the node. /// They are boxed because we want to keep them in a single list. /// Later `Listener::attach` will attach an actual listener to a DOM node. - pub fn add_listeners(&mut self, listeners: Vec>) { + pub fn add_listeners(&mut self, listeners: Vec>) { for listener in listeners { self.listeners.push(listener); } diff --git a/src/virtual_dom/vtext.rs b/src/virtual_dom/vtext.rs index 4633a4f13..97357fcd5 100644 --- a/src/virtual_dom/vtext.rs +++ b/src/virtual_dom/vtext.rs @@ -9,6 +9,7 @@ use stdweb::web::{document, Element, INode, Node, TextNode}; /// A type for a virtual /// [`TextNode`](https://developer.mozilla.org/en-US/docs/Web/API/Document/createTextNode) /// representation. +#[derive(Clone)] pub struct VText { /// Contains a text of the node. pub text: String, diff --git a/tests/derive_props/fail.rs b/tests/derive_props/fail.rs index 2b12dce83..568f8bf4f 100644 --- a/tests/derive_props/fail.rs +++ b/tests/derive_props/fail.rs @@ -4,8 +4,9 @@ use yew::prelude::*; mod t1 { use super::*; + #[derive(Clone)] struct Value; - #[derive(Properties)] + #[derive(Clone, Properties)] pub struct Props { // ERROR: optional params must implement default value: Value, @@ -14,7 +15,7 @@ mod t1 { mod t2 { use super::*; - #[derive(Properties)] + #[derive(Clone, Properties)] pub struct Props { // ERROR: optional is not a tag #[props(optional)] @@ -24,7 +25,7 @@ mod t2 { mod t3 { use super::*; - #[derive(Properties)] + #[derive(Clone, Properties)] pub struct Props { #[props(required)] value: String, @@ -37,7 +38,7 @@ mod t3 { mod t4 { use super::*; - #[derive(Properties)] + #[derive(Clone, Properties)] pub struct Props { b: i32, #[props(required)] diff --git a/tests/derive_props/fail.stderr b/tests/derive_props/fail.stderr index ca1eca72b..8f8f9cf38 100644 --- a/tests/derive_props/fail.stderr +++ b/tests/derive_props/fail.stderr @@ -1,31 +1,31 @@ error: expected `props(required)` - --> $DIR/fail.rs:20:11 + --> $DIR/fail.rs:21:11 | -20 | #[props(optional)] +21 | #[props(optional)] | ^^^^^ error[E0277]: the trait bound `t1::Value: std::default::Default` is not satisfied - --> $DIR/fail.rs:8:14 + --> $DIR/fail.rs:9:21 | -8 | #[derive(Properties)] - | ^^^^^^^^^^ the trait `std::default::Default` is not implemented for `t1::Value` +9 | #[derive(Clone, Properties)] + | ^^^^^^^^^^ the trait `std::default::Default` is not implemented for `t1::Value` | = note: required by `std::default::Default::default` error[E0599]: no method named `build` found for type `t3::PropsBuilder` in the current scope - --> $DIR/fail.rs:34:26 + --> $DIR/fail.rs:35:26 | -27 | #[derive(Properties)] - | - method `build` not found for this +28 | #[derive(Clone, Properties)] + | - method `build` not found for this ... -34 | Props::builder().build(); +35 | Props::builder().build(); | ^^^^^ method not found in `t3::PropsBuilder` error[E0599]: no method named `b` found for type `t4::PropsBuilder` in the current scope - --> $DIR/fail.rs:48:26 + --> $DIR/fail.rs:49:26 | -40 | #[derive(Properties)] - | - method `b` not found for this +41 | #[derive(Clone, Properties)] + | - method `b` not found for this ... -48 | Props::builder().b(1).a(2).build(); +49 | Props::builder().b(1).a(2).build(); | ^ help: there is a method with a similar name: `a` diff --git a/tests/derive_props/pass.rs b/tests/derive_props/pass.rs index 57165bb19..76ed11fc7 100644 --- a/tests/derive_props/pass.rs +++ b/tests/derive_props/pass.rs @@ -5,8 +5,8 @@ use yew::prelude::*; mod t1 { use super::*; - #[derive(Properties)] - pub struct Props { + #[derive(Clone, Properties)] + pub struct Props { value: T, } @@ -19,9 +19,10 @@ mod t1 { mod t2 { use super::*; + #[derive(Clone)] struct Value; - #[derive(Properties)] - pub struct Props { + #[derive(Clone, Properties)] + pub struct Props { #[props(required)] value: T, } @@ -34,7 +35,7 @@ mod t2 { mod t3 { use super::*; - #[derive(Properties)] + #[derive(Clone, Properties)] pub struct Props { #[props(required)] b: i32, @@ -50,10 +51,10 @@ mod t3 { mod t4 { use super::*; - #[derive(Properties)] + #[derive(Clone, Properties)] pub struct Props where - T: Default, + T: Clone + Default, { value: T, } @@ -67,8 +68,8 @@ mod t4 { mod t5 { use super::*; - #[derive(Properties)] - pub struct Props<'a, T: Default + 'a> { + #[derive(Clone, Properties)] + pub struct Props<'a, T: Clone + Default + 'a> { static_value: &'static str, #[props(required)] value: &'a T, diff --git a/tests/macro/html-component-fail.rs b/tests/macro/html-component-fail.rs index 5c2baef74..c2f447480 100644 --- a/tests/macro/html-component-fail.rs +++ b/tests/macro/html-component-fail.rs @@ -2,7 +2,7 @@ use yew::prelude::*; -#[derive(Properties, PartialEq)] +#[derive(Clone, Properties, PartialEq)] pub struct ChildProperties { pub string: String, #[props(required)] @@ -27,7 +27,7 @@ impl Component for Child { } } -#[derive(Properties)] +#[derive(Clone, Properties)] pub struct ChildContainerProperties { pub children: ChildrenWithProps, } diff --git a/tests/macro/html-component-fail.stderr b/tests/macro/html-component-fail.stderr index ea1a54284..eda4de366 100644 --- a/tests/macro/html-component-fail.stderr +++ b/tests/macro/html-component-fail.stderr @@ -109,8 +109,8 @@ error[E0609]: no field `unknown` on type `ChildProperties` error[E0599]: no method named `unknown` found for type `ChildPropertiesBuilder` in the current scope --> $DIR/html-component-fail.rs:65:20 | -5 | #[derive(Properties, PartialEq)] - | - method `unknown` not found for this +5 | #[derive(Clone, Properties, PartialEq)] + | - method `unknown` not found for this ... 65 | html! { }; | ^^^^^^^ method not found in `ChildPropertiesBuilder` @@ -170,8 +170,8 @@ help: you can convert an `u32` to `i32` and panic if the converted value wouldn' error[E0599]: no method named `string` found for type `ChildPropertiesBuilder` in the current scope --> $DIR/html-component-fail.rs:73:20 | -5 | #[derive(Properties, PartialEq)] - | - method `string` not found for this +5 | #[derive(Clone, Properties, PartialEq)] + | - method `string` not found for this ... 73 | html! { }; | ^^^^^^ method not found in `ChildPropertiesBuilder` @@ -179,8 +179,8 @@ error[E0599]: no method named `string` found for type `ChildPropertiesBuilder` in the current scope --> $DIR/html-component-fail.rs:77:5 | -5 | #[derive(Properties, PartialEq)] - | - method `children` not found for this +5 | #[derive(Clone, Properties, PartialEq)] + | - method `children` not found for this ... 77 | html! { { "Not allowed" } }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `ChildPropertiesBuilder` diff --git a/tests/macro/html-component-pass.rs b/tests/macro/html-component-pass.rs index 31b1b61b8..5d0daadab 100644 --- a/tests/macro/html-component-pass.rs +++ b/tests/macro/html-component-pass.rs @@ -3,7 +3,7 @@ use yew::prelude::*; use yew::html::ChildrenRenderer; -#[derive(Properties, Default, PartialEq)] +#[derive(Clone, Properties, Default, PartialEq)] pub struct ChildProperties { pub string: String, #[props(required)] @@ -30,7 +30,7 @@ impl Component for Child { } } -#[derive(Properties, Default)] +#[derive(Clone, Properties, Default)] pub struct ContainerProperties { #[props(required)] pub int: i32, @@ -55,7 +55,7 @@ impl Component for Container { } } -#[derive(Properties, Default)] +#[derive(Clone, Properties, Default)] pub struct ChildContainerProperties { #[props(required)] pub int: i32, @@ -165,12 +165,7 @@ fn compile_pass() { ::std::vec::Vec<_> { - vec![html!{ "String" }] - } - }()), + vec![html!{ "String" }] ) /> }; diff --git a/tests/macro/test_component.rs b/tests/macro/test_component.rs index 252c1846a..b4afc83b6 100644 --- a/tests/macro/test_component.rs +++ b/tests/macro/test_component.rs @@ -1,6 +1,6 @@ use yew::prelude::*; -#[derive(Properties, PartialEq)] +#[derive(Clone, Properties, PartialEq)] pub struct TestProperties { pub string: String, pub int: i32, diff --git a/tests/vcomp_test.rs b/tests/vcomp_test.rs index d3c7e5afe..f3e994700 100644 --- a/tests/vcomp_test.rs +++ b/tests/vcomp_test.rs @@ -8,7 +8,7 @@ wasm_bindgen_test_configure!(run_in_browser); struct Comp; -#[derive(PartialEq, Properties)] +#[derive(Clone, PartialEq, Properties)] struct Props { field_1: u32, field_2: u32, @@ -33,19 +33,19 @@ impl Component for Comp { #[test] fn set_properties_to_component() { - let _ = html! { + html! { }; - let _ = html! { + html! { }; - let _ = html! { + html! { }; - let _ = html! { + html! { }; @@ -54,7 +54,7 @@ fn set_properties_to_component() { field_2: 1, }; - let _ = html! { + html! { }; }