Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow mounting app component with props #567

Merged
merged 3 commits into from
Aug 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 66 additions & 19 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,35 @@ pub struct App<COMP: Component> {

impl<COMP> App<COMP>
where
COMP: Component<Properties = ()> + Renderable<COMP>,
COMP: Component + Renderable<COMP>,
COMP::Properties: Default,
{
/// Creates a new `App` with a component in a context.
pub fn new() -> Self {
let scope = Scope::new();
App { scope }
/// The main entrypoint of a yew program. It works similarly to the `program`
/// function in Elm. You should provide an initial model, `update` function
/// which will update the state of the model and a `view` function which
/// will render the model to a virtual DOM tree. If you would like to pass props,
/// use the `mount_with_props` method.
pub fn mount(self, element: Element) -> Scope<COMP> {
clear_element(&element);
self.scope
.mount_in_place(element, None, None, COMP::Properties::default())
}

/// Alias to `mount("body", ...)`.
pub fn mount_to_body(self) -> Scope<COMP> {
// Bootstrap the component for `Window` environment only (not for `Worker`)
let element = document()
.query_selector("body")
.expect("can't get body node for rendering")
.expect("can't unwrap body node");
self.mount(element)
}

/// Alias to `mount_in_place` taking a component having a body element at the
/// root of the HTML generated by its `view` method. Use this method when you
/// Alternative to `mount` which replaces the body element with a component which has a body
/// element at the root of the HTML generated by its `view` method. Use this method when you
/// need to manipulate the body element. For example, adding/removing app-wide
/// CSS classes of the body element.
pub fn replace_body(self) -> Scope<COMP> {
pub fn mount_as_body(self) -> Scope<COMP> {
let html_element = document()
.query_selector("html")
.expect("can't get html node for rendering")
Expand All @@ -36,26 +52,57 @@ where
html_element
.remove_child(&body_element)
.expect("can't remove body child");
self.scope.mount_in_place(html_element, None, None, ())
self.scope
.mount_in_place(html_element, None, None, COMP::Properties::default())
}
}

/// Alias to `mount("body", ...)`.
pub fn mount_to_body(self) -> Scope<COMP> {
impl<COMP> App<COMP>
where
COMP: Component + Renderable<COMP>,
{
/// Creates a new `App` with a component in a context.
pub fn new() -> Self {
let scope = Scope::new();
App { scope }
}

/// The main entrypoint of a yew program which also allows passing properties. It works
/// similarly to the `program` function in Elm. You should provide an initial model, `update`
/// function which will update the state of the model and a `view` function which
/// will render the model to a virtual DOM tree.
pub fn mount_with_props(self, element: Element, props: COMP::Properties) -> Scope<COMP> {
clear_element(&element);
self.scope.mount_in_place(element, None, None, props)
}

/// Alias to `mount_with_props("body", ...)`.
pub fn mount_to_body_with_props(self, props: COMP::Properties) -> Scope<COMP> {
// Bootstrap the component for `Window` environment only (not for `Worker`)
let element = document()
.query_selector("body")
.expect("can't get body node for rendering")
.expect("can't unwrap body node");
self.mount(element)
self.mount_with_props(element, props)
}

/// The main entrypoint of a yew program. It works similar as `program`
/// function in Elm. You should provide an initial model, `update` function
/// which will update the state of the model and a `view` function which
/// will render the model to a virtual DOM tree.
pub fn mount(self, element: Element) -> Scope<COMP> {
clear_element(&element);
self.scope.mount_in_place(element, None, None, ())
/// Alternative to `mount_with_props` which replaces the body element with a component which
/// has a body element at the root of the HTML generated by its `view` method. Use this method
/// when you need to manipulate the body element. For example, adding/removing app-wide
/// CSS classes of the body element.
pub fn mount_as_body_with_props(self, props: COMP::Properties) -> Scope<COMP> {
let html_element = document()
.query_selector("html")
.expect("can't get html node for rendering")
.expect("can't unwrap html node");
let body_element = document()
.query_selector("body")
.expect("can't get body node for rendering")
.expect("can't unwrap body node");
html_element
.remove_child(&body_element)
.expect("can't remove body child");
self.scope.mount_in_place(html_element, None, None, props)
}
}

Expand Down
13 changes: 12 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,24 @@ pub fn run_loop() {
/// Starts an app mounted to a body of the document.
jstarry marked this conversation as resolved.
Show resolved Hide resolved
pub fn start_app<COMP>()
where
COMP: Component<Properties = ()> + Renderable<COMP>,
COMP: Component + Renderable<COMP>,
COMP::Properties: Default,
{
initialize();
App::<COMP>::new().mount_to_body();
run_loop();
}

/// Starts an app mounted to a body of the document.
pub fn start_app_with_props<COMP>(props: COMP::Properties)
where
COMP: Component + Renderable<COMP>,
{
initialize();
App::<COMP>::new().mount_to_body_with_props(props);
run_loop();
}

/// The Yew Prelude
///
/// The purpose of this module is to alleviate imports of many common types:
Expand Down