[Go WebAssembly] Event Binding - addEventListener Example


In this post, we will show you how to use addEventListener method in Go wasm.

First install godom to help DOM manipulation:

$ GOARCH=wasm GOOS=js go get -u github.com/siongui/godom/wasm

Click the text in the following demo several times to see what happens.

Go Wasm addEventListener Demo

The following is source code of demo:

Go:

package main

import (
      "fmt"
      "syscall/js"

      . "github.com/siongui/godom/wasm"
)

var signal = make(chan int)

func keepAlive() {
      for {
              <-signal
      }
}

func main() {
      foo := Document.GetElementById("foo")
      count := 0

      cb := js.NewCallback(func(args []js.Value) {
              count++
              foo.Set("textContent", fmt.Sprintf("I am clicked %d time", count))
      })
      foo.Call("addEventListener", "click", cb)

      keepAlive()
}

We use NewCallback method in syscall/js package to create the callback for the click event of the div element. The most tricky and strange part of the above code is the use of keepAlive func to prevent main func from exiting. If you do not do this, you will see the following error message in the developer console when clicking on the text in the demo:

bad callback: Go program has already exited

In the beginning I did not use keepAlive func and always saw the above error message when clicking on the text. After some searches, I found the answer in [2], which uses keepAlive func to prevent main from exiting.

HTML:

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>Go wasm - addEventListener</title>
</head>
<body>
  <div id="foo">Click Here</div>

  <!-- https://github.com/golang/go/blob/master/misc/wasm/wasm_exec.js -->
  <script src="wasm_exec.js"></script>
  <script>
      const go = new Go();
      let mod, inst;
      WebAssembly.instantiateStreaming(
              fetch("click.wasm", {cache: 'no-cache'}), go.importObject).then((result) => {
              mod = result.module;
              inst = result.instance;
              run();
      });
      async function run() {
              await go.run(inst);
      };
  </script>
</body>
</html>

Nothing special in above HTML code. Most of the HTML code is to load compiled wasm module. If you have no idea what it means, see [1].

The full source code is also available in my GitHub repo.


Tested on:

  • Ubuntu Linux 18.04
  • Go 1.11.1
  • Chromium Version 69.0.3497.81 on Ubuntu 18.04 (64-bit)

References:

[1][Go WebAssembly] First Wasm Program - Hello World
[2]
[3]Event Binding - addEventListener in Go (GopherJS)