Skip to main content

wal_core/component/
mod.rs

1use crate::virtual_dom::VNode;
2use std::any::Any;
3use std::hash::Hash;
4
5use self::behavior::{AnyComponentBehavior, Behavior};
6
7pub mod behavior;
8pub mod callback;
9pub(crate) mod node;
10pub(crate) mod scheduler;
11
12/// Trait for defining custom component.
13///
14/// It adapts a MVC pattern.
15/// Model is the fields and state of the component. It is initialized by [new](#tymethod.new) function using [Properties](#associatedtype.Properties).
16/// View is the function [view](#tymethod.view) that returns a view of an application.
17/// Controller is the function [update](#tymethod.update) that updates the model based on the [Message](#associatedtype.Message).
18pub trait Component: Sized {
19    /// Type to describe the message that can be sent to the component.
20    /// It is used to update the model of the component.
21    type Message: 'static;
22
23    /// Type to describe the properties that can be passed to the component.
24    /// It is used to initialize the model of the component.
25    type Properties: Hash + 'static;
26
27    /// Function that creates a new instance of the component therefore initialize a model using [Properties](#associatedtype.Properties).
28    fn new(props: Self::Properties) -> Self;
29
30    /// Function that returns a view of the component.
31    /// It uses [Behavior](behavior::Behavior) to create [Callbacks](callback::Callback) that are responsible to send [Messages](#associatedtype.Message) to the component.
32    /// Defining the views is done using [rsx](../../wal_rsx/macro.rsx.html) macro.
33    /// Using the macro is not mandatory but it is recommended and makes in unnecessary to know the complex structure of [VNode].
34    fn view(&self, behavior: &mut impl Behavior<Self>) -> VNode;
35
36    /// Function that updates the model of the component based on the [Message](#associatedtype.Message).
37    /// It returns a boolean that indicates if the rerender of the component is necessary.
38    /// Meaning whether the view of the component should be updated or not.
39    fn update(&mut self, message: Self::Message) -> bool;
40}
41
42pub(crate) trait AnyComponent {
43    fn new(props: Box<dyn Any>) -> Self
44    where
45        Self: Sized;
46    fn view(&self, behavior: &mut AnyComponentBehavior) -> VNode;
47    fn update(&mut self, message: Box<dyn Any>) -> bool;
48}
49
50impl<C: Component> AnyComponent for C {
51    fn new(props: Box<dyn Any>) -> Self {
52        let props = *props.downcast::<C::Properties>().expect(
53            "Failed to downcast properties in any component to properties of a real component",
54        );
55        C::new(props)
56    }
57
58    fn view(&self, any_component_behavior: &mut AnyComponentBehavior) -> VNode {
59        self.view(any_component_behavior)
60    }
61
62    fn update(&mut self, message: Box<dyn Any>) -> bool {
63        let msg = *message
64            .downcast::<C::Message>()
65            .expect("Failed to downcast message in any component to message of a real component");
66        self.update(msg)
67    }
68}