use crate::{
component::{Comp, Component, RcComp},
routing::{self, Routes},
};
use wasm_bindgen::UnwrapThrowExt;
pub trait Application: Component {
fn init(comp: &Comp<Self>) -> Self;
fn init_router(_comp: &Comp<Self>) -> Option<<<Self as Component>::Routes as Routes>::Router> {
None
}
fn mount_to_element(root: web_sys::Element) {
let rc_comp = mount_to_element::<Self>(root);
std::mem::forget(rc_comp);
}
fn mount_to_element_id(id: &str) {
let root = crate::utils::document()
.get_element_by_id(id)
.expect_throw("No element associated with the specified id (to use as a root element)");
Self::mount_to_element(root);
}
fn mount_to_body() {
let root = crate::utils::document()
.body()
.expect("document body")
.into();
Self::mount_to_element(root);
}
}
pub fn mount_to_element<A: Application>(root: web_sys::Element) -> RcComp<A> {
root.set_text_content(None);
let rc_comp = RcComp::with_ws_root(root);
let comp = rc_comp.comp();
match A::init_router(&comp) {
Some(router) => routing::set_router(router),
None if std::any::TypeId::of::<()>()
!= std::any::TypeId::of::<<<A as Component>::Routes as Routes>::Router>() =>
{
log::warn!(
"You may want to implement `Application::init_router()` to return Some(router)"
);
}
_ => {}
}
let state = Application::init(&comp);
rc_comp.set_state(state);
routing::execute_routing::<<<A as Component>::Routes as Routes>::Router>();
rc_comp.first_render();
rc_comp
}