rustwebassemblywasm-bindgenweb-sys

How to add an event listener to some HTML element from Rust which calls a trivial JS function?


I have the "on_event" JS function:

function on_event(event) {
    console.log(event);
}

And I have the "button" HTML element builder in Rust:

let window = web_sys::window().expect("no `window` object");
let document = window.document().expect("no `document` object");
let body = document.body().expect("no `body` object");

let button = document.create_element("button")?;
// ...
body.append_child(&button);

How to link the "on_event" JS function with the "button" HTML element from the Rust code?

At the end I need something like:

button.add_event_listener("click", "on_event"); // <- What I need to use here instead of this code

Solution

  • For a trivial JS function I can use HTML attributes:

    button.set_attribute("onclick", "on_event('on_event callback fired!')")?;
    

    Also it can be used for Rust functions exported to JS with #[wasm_bindgen] and imported to the global namespace.

    In Rust:

    #[wasm_bindgen]
    pub fn on_event(message: &str) {
      console_log(message);
    }
    
    // ...
    
    button.set_attribute("onclick", "wasm.on_event('on_event callback fired!')")?;
    

    In JS:

    <script type="module">
      import init from './pkg/wasm_project.js';
      window.wasm = await init('./pkg/wasm_project_bg.wasm');
    </script>
    

    If you are using Trunk then instead of edit of JS file you can create Trunk.toml file in the root of the project folder and put this code:

    [build]
    pattern_script = "<script type=\"module\">import init, * as wasm from '{base}{js}';init('{base}{wasm}').then(()=>window.wasm=wasm);</script>"