tachys/html/element/
element_ext.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use crate::{
    html::{
        attribute::Attribute,
        class::IntoClass,
        event::{on, EventDescriptor},
        style::IntoStyle,
    },
    renderer::RemoveEventHandler,
};
use wasm_bindgen::JsValue;
use web_sys::Element;

/// Extends an HTML element, allowing you to add attributes and children to the
/// element's built state at runtime, with a similar API to how they
/// can be added to the static view tree at compile time.
///
/// ```rust,ignore
/// use tachys::html::element::ElementExt;
///
/// let view: HtmlElement<_, _, _, MockDom> = button();
///
/// // add an event listener as part of the static type
/// // this will be lazily added when the element is built
/// let view = element.on(ev::click, move |_| /* ... */);
///
/// // `element` now contains the actual element
/// let element = element.build();
/// let remove = element.on(ev::blur, move |_| /* ... */);
/// ```
pub trait ElementExt {
    /// Adds an attribute to the element, at runtime.
    fn attr<At>(&self, attribute: At) -> At::State
    where
        At: Attribute;

    /// Adds a class to the element, at runtime.
    fn class<C>(&self, class: C) -> C::State
    where
        C: IntoClass;

    /// Adds a style to the element, at runtime.
    fn style<S>(&self, style: S) -> S::State
    where
        S: IntoStyle;

    /// Adds an event listener to the element, at runtime.
    fn on<E>(
        &self,
        ev: E,
        cb: impl FnMut(E::EventType) + 'static,
    ) -> RemoveEventHandler<Element>
    where
        E: EventDescriptor + Send + 'static,
        E::EventType: 'static,
        E::EventType: From<JsValue>;
}

impl<T> ElementExt for T
where
    T: AsRef<Element>,
{
    fn attr<At>(&self, attribute: At) -> At::State
    where
        At: Attribute,
    {
        attribute.build(self.as_ref())
    }

    fn class<C>(&self, class: C) -> C::State
    where
        C: IntoClass,
    {
        class.build(self.as_ref())
    }

    fn on<E>(
        &self,
        ev: E,
        cb: impl FnMut(E::EventType) + 'static,
    ) -> RemoveEventHandler<Element>
    where
        E: EventDescriptor + Send + 'static,
        E::EventType: 'static,
        E::EventType: From<JsValue>,
    {
        on::<E, _>(ev, cb).attach(self.as_ref())
    }

    fn style<S>(&self, style: S) -> S::State
    where
        S: IntoStyle,
    {
        style.build(self.as_ref())
    }
}