This is unreleased documentation for Yew Next version.
For up-to-date documentation, see the latest version on docs.rs.

yew/html/
mod.rs

1//! The main html module which defines components, listeners, and class helpers.
2
3mod classes;
4mod component;
5mod conversion;
6mod error;
7mod listener;
8
9use std::cell::RefCell;
10use std::rc::Rc;
11
12pub use classes::*;
13pub use component::*;
14pub use conversion::*;
15pub use error::*;
16pub use listener::*;
17use wasm_bindgen::JsValue;
18use web_sys::{Element, Node};
19
20use crate::sealed::Sealed;
21use crate::virtual_dom::{VNode, VPortal};
22
23/// A type which expected as a result of `view` function implementation.
24pub type Html = VNode;
25
26/// An enhanced type of `Html` returned in suspendible function components.
27pub type HtmlResult = RenderResult<Html>;
28
29impl Sealed for HtmlResult {}
30impl Sealed for Html {}
31
32/// A trait to translate into a [`HtmlResult`].
33pub trait IntoHtmlResult: Sealed {
34    /// Performs the conversion.
35    fn into_html_result(self) -> HtmlResult;
36}
37
38impl IntoHtmlResult for HtmlResult {
39    #[inline(always)]
40    fn into_html_result(self) -> HtmlResult {
41        self
42    }
43}
44impl IntoHtmlResult for Html {
45    #[inline(always)]
46    fn into_html_result(self) -> HtmlResult {
47        Ok(self)
48    }
49}
50
51/// Wrapped Node reference for later use in Component lifecycle methods.
52///
53/// # Example
54/// Focus an `<input>` element on mount.
55/// ```
56/// use web_sys::HtmlInputElement;
57/// # use yew::prelude::*;
58///
59/// pub struct Input {
60///     node_ref: NodeRef,
61/// }
62///
63/// impl Component for Input {
64///     type Message = ();
65///     type Properties = ();
66///
67///     fn create(_ctx: &Context<Self>) -> Self {
68///         Input {
69///             node_ref: NodeRef::default(),
70///         }
71///     }
72///
73///     fn rendered(&mut self, _ctx: &Context<Self>, first_render: bool) {
74///         if first_render {
75///             if let Some(input) = self.node_ref.cast::<HtmlInputElement>() {
76///                 input.focus();
77///             }
78///         }
79///     }
80///
81///     fn view(&self, _ctx: &Context<Self>) -> Html {
82///         html! {
83///             <input ref={self.node_ref.clone()} type="text" />
84///         }
85///     }
86/// }
87/// ```
88/// ## Relevant examples
89/// - [Node Refs](https://github.com/yewstack/yew/tree/master/examples/node_refs)
90#[derive(Default, Clone)]
91pub struct NodeRef(Rc<RefCell<NodeRefInner>>);
92
93impl PartialEq for NodeRef {
94    fn eq(&self, other: &Self) -> bool {
95        self.0.as_ptr() == other.0.as_ptr()
96    }
97}
98
99impl std::fmt::Debug for NodeRef {
100    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101        write!(
102            f,
103            "NodeRef {{ references: {:?} }}",
104            self.get().map(|n| crate::utils::print_node(&n))
105        )
106    }
107}
108
109#[derive(PartialEq, Debug, Default, Clone)]
110struct NodeRefInner {
111    node: Option<Node>,
112}
113
114impl NodeRef {
115    /// Get the wrapped Node reference if it exists
116    pub fn get(&self) -> Option<Node> {
117        let inner = self.0.borrow();
118        inner.node.clone()
119    }
120
121    /// Try converting the node reference into another form
122    pub fn cast<INTO: AsRef<Node> + From<JsValue>>(&self) -> Option<INTO> {
123        let node = self.get();
124        node.map(Into::into).map(INTO::from)
125    }
126}
127
128#[cfg(feature = "csr")]
129mod feat_csr {
130    use super::*;
131
132    impl NodeRef {
133        pub(crate) fn set(&self, new_ref: Option<Node>) {
134            let mut inner = self.0.borrow_mut();
135            inner.node = new_ref;
136        }
137    }
138}
139
140/// Render children into a DOM node that exists outside the hierarchy of the parent
141/// component.
142/// ## Relevant examples
143/// - [Portals](https://github.com/yewstack/yew/tree/master/examples/portals)
144pub fn create_portal(child: Html, host: Element) -> Html {
145    VNode::VPortal(Rc::new(VPortal::new(child, host)))
146}