yew_stdweb/virtual_dom/
vtext.rs1use super::{AttrValue, VDiff, VNode};
4use crate::html::{AnyScope, NodeRef};
5use crate::utils::document;
6use cfg_if::cfg_if;
7use log::warn;
8use std::cmp::PartialEq;
9cfg_if! {
10 if #[cfg(feature = "std_web")] {
11 use stdweb::web::{Element, INode, TextNode};
12 } else if #[cfg(feature = "web_sys")] {
13 use web_sys::{Element, Text as TextNode};
14 }
15}
16
17#[derive(Clone, Debug)]
21pub struct VText {
22 pub text: AttrValue,
24 pub reference: Option<TextNode>,
26}
27
28impl VText {
29 pub fn new(text: impl Into<AttrValue>) -> Self {
31 VText {
32 text: text.into(),
33 reference: None,
34 }
35 }
36}
37
38impl VDiff for VText {
39 fn detach(&mut self, parent: &Element) {
41 let node = self
42 .reference
43 .take()
44 .expect("tried to remove not rendered VText from DOM");
45 if parent.remove_child(&node).is_err() {
46 warn!("Node not found to remove VText");
47 }
48 }
49
50 fn apply(
52 &mut self,
53 _parent_scope: &AnyScope,
54 parent: &Element,
55 next_sibling: NodeRef,
56 ancestor: Option<VNode>,
57 ) -> NodeRef {
58 if let Some(mut ancestor) = ancestor {
59 if let VNode::VText(mut vtext) = ancestor {
60 self.reference = vtext.reference.take();
61 let text_node = self
62 .reference
63 .clone()
64 .expect("Rendered VText nodes should have a ref");
65 if self.text != vtext.text {
66 text_node.set_node_value(Some(&self.text));
67 }
68
69 return NodeRef::new(text_node.into());
70 }
71
72 ancestor.detach(parent);
73 }
74
75 let text_node = document().create_text_node(&self.text);
76 super::insert_node(&text_node, parent, next_sibling.get());
77 self.reference = Some(text_node.clone());
78 NodeRef::new(text_node.into())
79 }
80}
81
82impl PartialEq for VText {
83 fn eq(&self, other: &VText) -> bool {
84 self.text == other.text
85 }
86}
87
88#[cfg(test)]
89mod test {
90 extern crate self as yew;
91
92 use crate::html;
93
94 #[cfg(feature = "wasm_test")]
95 use wasm_bindgen_test::{wasm_bindgen_test as test, wasm_bindgen_test_configure};
96
97 #[cfg(feature = "wasm_test")]
98 wasm_bindgen_test_configure!(run_in_browser);
99
100 #[test]
101 fn text_as_root() {
102 html! {
103 "Text Node As Root"
104 };
105
106 html! {
107 { "Text Node As Root" }
108 };
109 }
110}
111
112#[cfg(all(test, feature = "web_sys"))]
113mod layout_tests {
114 extern crate self as yew;
115
116 use crate::html;
117 use crate::virtual_dom::layout_tests::{diff_layouts, TestLayout};
118
119 #[cfg(feature = "wasm_test")]
120 use wasm_bindgen_test::{wasm_bindgen_test as test, wasm_bindgen_test_configure};
121
122 #[cfg(feature = "wasm_test")]
123 wasm_bindgen_test_configure!(run_in_browser);
124
125 #[test]
126 fn diff() {
127 let layout1 = TestLayout {
128 name: "1",
129 node: html! { "a" },
130 expected: "a",
131 };
132
133 let layout2 = TestLayout {
134 name: "2",
135 node: html! { "b" },
136 expected: "b",
137 };
138
139 let layout3 = TestLayout {
140 name: "3",
141 node: html! {
142 <>
143 {"a"}
144 {"b"}
145 </>
146 },
147 expected: "ab",
148 };
149
150 let layout4 = TestLayout {
151 name: "4",
152 node: html! {
153 <>
154 {"b"}
155 {"a"}
156 </>
157 },
158 expected: "ba",
159 };
160
161 diff_layouts(vec![layout1, layout2, layout3, layout4]);
162 }
163}