1use crate::html::{Component, ComponentLink, NodeRef, Scope};
5use crate::utils::document;
6use cfg_if::cfg_if;
7cfg_if! {
8 if #[cfg(feature = "std_web")] {
9 use stdweb::web::{Element, INode, IParentNode};
10 } else if #[cfg(feature = "web_sys")] {
11 use web_sys::Element;
12 }
13}
14
15#[derive(Debug)]
17pub struct App<COMP: Component> {
18 scope: Scope<COMP>,
20}
21
22impl<COMP> Default for App<COMP>
23where
24 COMP: Component,
25{
26 fn default() -> Self {
27 App::new()
28 }
29}
30
31impl<COMP> App<COMP>
32where
33 COMP: Component,
34 COMP::Properties: Default,
35{
36 pub fn mount(self, element: Element) -> ComponentLink<COMP> {
42 clear_element(&element);
43 self.scope.mount_in_place(
44 element,
45 NodeRef::default(),
46 NodeRef::default(),
47 COMP::Properties::default(),
48 )
49 }
50
51 pub fn mount_to_body(self) -> ComponentLink<COMP> {
53 let element = document()
55 .query_selector("body")
56 .expect("can't get body node for rendering")
57 .expect("can't unwrap body node");
58 self.mount(element)
59 }
60
61 pub fn mount_as_body(self) -> ComponentLink<COMP> {
66 let html_element = document()
67 .query_selector("html")
68 .expect("can't get html node for rendering")
69 .expect("can't unwrap html node");
70 let body_element = document()
71 .query_selector("body")
72 .expect("can't get body node for rendering")
73 .expect("can't unwrap body node");
74 html_element
75 .remove_child(&body_element)
76 .expect("can't remove body child");
77 self.scope.mount_in_place(
78 html_element,
79 NodeRef::default(),
80 NodeRef::default(),
81 COMP::Properties::default(),
82 )
83 }
84}
85
86impl<COMP> App<COMP>
87where
88 COMP: Component,
89{
90 pub fn new() -> Self {
92 let scope = Scope::new(None);
93 App { scope }
94 }
95
96 pub fn mount_with_props(
101 self,
102 element: Element,
103 props: COMP::Properties,
104 ) -> ComponentLink<COMP> {
105 clear_element(&element);
106 self.scope
107 .mount_in_place(element, NodeRef::default(), NodeRef::default(), props)
108 }
109
110 pub fn mount_to_body_with_props(self, props: COMP::Properties) -> ComponentLink<COMP> {
112 let element = document()
114 .query_selector("body")
115 .expect("can't get body node for rendering")
116 .expect("can't unwrap body node");
117 self.mount_with_props(element, props)
118 }
119
120 pub fn mount_as_body_with_props(self, props: COMP::Properties) -> ComponentLink<COMP> {
125 let html_element = document()
126 .query_selector("html")
127 .expect("can't get html node for rendering")
128 .expect("can't unwrap html node");
129 let body_element = document()
130 .query_selector("body")
131 .expect("can't get body node for rendering")
132 .expect("can't unwrap body node");
133 html_element
134 .remove_child(&body_element)
135 .expect("can't remove body child");
136 self.scope
137 .mount_in_place(html_element, NodeRef::default(), NodeRef::default(), props)
138 }
139}
140
141fn clear_element(element: &Element) {
143 while let Some(child) = element.last_child() {
144 element.remove_child(&child).expect("can't remove a child");
145 }
146}