Macro impl_update_elements

Source
macro_rules! impl_update_elements {
    ($name:ident, $json:ty, $($element:ident),*) => { ... };
}
Expand description

UI macro: implements methods to update UI elements.

Given a name, this macro implements the methods update_name_inactive_elements and update_name_all_elements. Both methods have the signature fn ...(&self, json: &$json) -> Result<(), JsValue>.

These methods are intended to be called when a JSON response has been received, in order to keep the values of the UI elements synchronized with their server-side values.

The difference between the _inactive_elements and _all_elements methods is that the former does not update active elements, in order to avoid overriding the input that the user might be typing in a field.

The functions call a post_update_name_elements method with the same signature, which can implement any custom functionality. If no custom functionality is needed, a dummy method that does nothing can be implemented with the impl_post_update_noop macro.

ยงExample

use maia_wasm::{impl_dummy_preferences, impl_post_update_noop, impl_update_elements,
                ui_elements, ui::input::NumberInput};
use serde::{Deserialize, Serialize};
use std::{cell::RefCell, rc::Rc};
use wasm_bindgen::JsValue;
use web_sys::{Document, HtmlInputElement, Window};

// An object defined by a REST API. This corresponds to the GET method.
#[derive(Debug, Serialize, Deserialize)]
struct MyObject {
    my_integer: u64,
    my_float: f32,
}

#[derive(Clone)]
struct Ui {
    window: Rc<Window>,
    document: Rc<Document>,
    elements: Elements,
    preferences: Rc<RefCell<Preferences>>,
}

ui_elements! {
    my_object_my_integer: HtmlInputElement => NumberInput<u64>,
    my_object_my_float: HtmlInputElement => NumberInput<f32>,
}

// Dummy Preferences struct. This is needed because update_elements
// keeps the preferences in sync, so it calls methods in the Preferences.
struct Preferences {}
impl_dummy_preferences!(
    my_object_my_integer: u64,
    my_object_my_float: f32,
);

impl Ui {
    fn new(window: Rc<Window>, document: Rc<Document>) -> Result<Ui, JsValue> {
        let elements = Elements::new(&document)?;
        let preferences = Rc::new(RefCell::new(Preferences {}));
        let ui = Ui { window, document, elements, preferences };
        Ok(ui)
    }

    impl_update_elements!(my_object, MyObject, my_integer, my_float);
    impl_post_update_noop!(my_object, MyObject);
}

fn main() -> Result<(), JsValue> {
    let (window, document) = maia_wasm::get_window_and_document()?;
    let ui = Ui::new(window, document)?;

    // assume that the following data has come from a REST API GET
    let response = MyObject { my_integer: 42, my_float: 3.14 };
    ui.update_my_object_all_elements(&response);

    Ok(())
}