Opa: How to Interact With the Database Without Blocking the UI

308 Views Asked by At

The Setup

I have a (rather standard) form that allows a user to create an account by entering a username and password. When the #username field loses focus, the database is queried to see if the supplied username is available.

The Problem

Everything works as expected, but the user interface is blocked from when the onblur event of #username is triggered until the database returns a value. How can check the database in an asyncronous and non-blocking fashion?

Here's my code (I've pulled most of this code out of example Opa projects):

Types

@abstract type User.ref = string

type User.t = 
  { username : string
  ; passwd : string
  }

type User.map('a) = ordered_map(User.ref, 'a, String.order)

Database

db /user : User.map(User.t)

Form

<form>
  <input id=#username type="text" onblur={_ -> username_available() } placeholder="username" />
  <input id=#password type="password" placeholder="password" />
</form>

Actions

username_available() : void =
  user = Dom.get_value(#username)
  match (get_user(user)) with
  | { none } -> Log.notice("username available:", "YES")
  | { some = _ } -> Log.notice("username available:", "NO")

get_user(username : string) : option(User.t) =
  match ?/user[username] with
  | { none } -> Option.none
  | { ~some } -> Option.some(some)

Thanks for your help.

1

There are 1 best solutions below

1
On BEST ANSWER

Very good question. The answer is quite simple: add @async directive before your username_available function. It is still somewhat experimental and therefore not documented. Any feedback welcome!

PS. A detail, but if you include simple code, personally I'd rather see a complete listing in one go (easier to copy&paste&run); possibly with comments in place of headers.