diff --git a/smart-house-web/frontend/src/main.rs b/smart-house-web/frontend/src/main.rs index be163b3..da7fc9a 100644 --- a/smart-house-web/frontend/src/main.rs +++ b/smart-house-web/frontend/src/main.rs @@ -1,100 +1,88 @@ #![allow(non_snake_case)] -use leptos::ev::SubmitEvent; use leptos::prelude::*; #[component] fn App() -> impl IntoView { - view! { -

"Controlled Component"

- -

"Uncontrolled Component"

- - } -} - -#[component] -fn ControlledComponent() -> impl IntoView { - // create a signal to hold the value - let (name, set_name) = signal("Controlled".to_string()); + let (value, set_value) = signal(0); + let is_odd = move || value.get() & 1 == 1; + let odd_text = move || if is_odd() { Some("How odd!") } else { None }; view! { - "Control Flow" + + // Simple UI to update and show a value + +

"Value is: " {value}

+ +
+ +

"Option"

+ // For any `T` that implements `IntoView`, + // so does `Option` + +

{odd_text}

+ // This means you can use `Option` methods on it +

{move || odd_text().map(|text| text.len())}

+ +

"Conditional Logic"

+ // You can do dynamic conditional if-then-else + // logic in several ways + // + // a. An "if" expression in a function + // This will simply re-render every time the value + // changes, which makes it good for lightweight UI +

+ {move || if is_odd() { + "Odd" + } else { + "Even" + }} +

+ + // b. Toggling some kind of class + // This is smart for an element that's going to + // toggled often, because it doesn't destroy + // it in between states + // (you can find the `hidden` class in `index.html`) +

"Appears if even."

+ + // c. The component + // This only renders the fallback and the child + // once, lazily, and toggles between them when + // needed. This makes it more efficient in many cases + // than a {move || if ...} block + "Even steven"

} + > +

"Oddment"

+
+ + // d. Because `bool::then()` converts a `bool` to + // `Option`, you can use it to create a show/hide toggled + {move || is_odd().then(|| view! {

"Oddity!"

})} + +

"Converting between Types"

+ // e. Note: if branches return different types, + // you can convert between them with + // `.into_any()` or using the `Either` enums + // (`Either`, `EitherOf3`, `EitherOf4`, etc.) + {move || match is_odd() { + true if value.get() == 1 => { + //
 returns HtmlElement
+                view! { 
"One"
}.into_any() + }, + false if value.get() == 2 => { + //

returns HtmlElement

+ // so we convert into a more generic type + view! {

"Two"

}.into_any() } - - // the `prop:` syntax lets you update a DOM property, - // rather than an attribute. - // - // IMPORTANT: the `value` *attribute* only sets the - // initial value, until you have made a change. - // The `value` *property* sets the current value. - // This is a quirk of the DOM; I didn't invent it. - // Other frameworks gloss this over; I think it's - // more important to give you access to the browser - // as it really works. - // - // tl;dr: use prop:value for form inputs - prop:value=name - /> -

"Name is: " {name}

+ _ => view! { }.into_any() + }} } } -#[component] -fn UncontrolledComponent() -> impl IntoView { - // import the type for - use leptos::html::Input; - - let (name, set_name) = signal("Uncontrolled".to_string()); - - // we'll use a NodeRef to store a reference to the input element - // this will be filled when the element is created - let input_element: NodeRef = NodeRef::new(); - - // fires when the form `submit` event happens - // this will store the value of the in our signal - let on_submit = move |ev: SubmitEvent| { - // stop the page from reloading! - ev.prevent_default(); - - // here, we'll extract the value from the input - let value = input_element - .get() - // event handlers can only fire after the view - // is mounted to the DOM, so the `NodeRef` will be `Some` - .expect(" to exist") - // `NodeRef` implements `Deref` for the DOM element type - // this means we can call`HtmlInputElement::value()` - // to get the current value of the input - .value(); - set_name.set(value); - }; - - view! { -
- - -
-

"Name is: " {name}

- } -} - -// This `main` function is the entry point into the app -// It just mounts our component to the -// Because we defined it as `fn App`, we can now use it in a -// template as fn main() { leptos::mount::mount_to_body(App) }