🏠 back to Observable

Compose UIs (spatially and temporally)

Make complex UIs (a.k.a. views) from simpler ones.

Wraps the hypertext literal with an extra special case for [key, DOM]. This allows you to design a custom UI using HTML, and tell the custom template how to bind sub-views to properties of the parent value. Simple but powerful.

viewof composite = view`<div style="display: flex">
<table>
  <tr>
    <td>${["r1", Range([0, 10])]}</td>
  </tr>
  <tr>
    <td>${["r2", Range([0, 3])]}</td>
  </tr>
  <tr>
    <td>${[
      "text",
      Text({
        label: "Enter some text"
      })
    ]}</td>
  </tr>
</table>
<img width="200"src="https://media.giphy.com/media/2vobTwCkFg88ZUnilt/giphy-downsized.gif"></img>
</div>
`
7 Likes

So the above is how to compose views spatially, but I have found the need to compose views temporally =>

Sequences of UIs are composed by yielding DOM elements. This is quite nice as you can carry state over the top and make programatic choices etc. E.g.:

viewof example1 = viewroutine(async function*() {
  let newName = undefined;
  while (true) {
    newName = yield* ask(
      Inputs.text({
        label: "please enter the name of the thing to create",
        minlength: 1,
        value: newName,
        submit: true
      })
    );
    yield md`<mark>updating to ${newName}`; // Note we can remember newName
    await new Promise(r => setTimeout(r, 1000)); // Mock async action
    yield* ask(htl.html`${md`<mark>updated`} ${Inputs.button("Again?")}`);
  }
})
1 Like