Step 4 of 6

Where views come from

A view can be more than a string: a function that builds it from data, a URL, an object with hooks, or a component from your framework.

Live exampleOpen ↗

Each tile says where its view comes from, and each view shows it again at the top. Both fish open the same function with different props; Opening hours is fetched from another file. Add a fish: the shop repaints when you come back.

The code

const basket = []
const fishes = { Clownfish: 'clownfish', 'Blue tang': 'tang' }

const app = new Zumly({
  mount: '.canvas',
  initialView: 'shop',
  views: {
    // A function: paints from state, and again each time you come back
    shop: ({ target, onActivate }) => {
      target.className = 'z-view shop'
      const paint = () => {
        target.innerHTML = `
          <h1>Fish shop</h1>
          <p>Basket: ${basket.join(', ') || 'empty'}</p>
          <div class="row">
            <div class="zoom-me tile clownfish" data-to="fish" data-name="Clownfish">Clownfish<small>function + props</small></div>
            <div class="zoom-me tile tang" data-to="fish" data-name="Blue tang">Blue tang<small>function + props</small></div>
            <div class="zoom-me tile hours" data-to="hours">Opening hours<small>URL</small></div>
          </div>`
      }
      paint()
      onActivate(paint)
    },
    // One function for both fish: the trigger's data-* arrive as props
    fish: ({ target, props }) => {
      target.className = `z-view card ${fishes[props.name]}`
      target.dataset.title = props.name
      target.innerHTML = `
        <span class="source">fish({ props: { name: '${props.name}' } })</span>
        <h2>${props.name}</h2>
        <button>Add to basket</button>`
      target.querySelector('button').onclick = () => {
        basket.push(props.name)
        app.zoomOut()
      }
    },
    // A URL: fetched the first time, then cached
    hours: 'hours.html'
  },
  lateralNav: false
})
app.init()

hours.html

<div class="z-view card hours" data-title="Opening hours">
  <span class="source">fetched from hours.html</span>
  <h2>Opening hours</h2>
  <p>Every day, 9 to 18.</p>
</div>

How it works

SourceExample
HTML string'<div class="z-view">…</div>'
URL'views/detail.html'
Function({ target, props, onActivate, onCleanup }) => { … }
Object{ title: 'Detail', render (ctx) { … }, mounted (node) { … } }
Elementdocument.querySelector('#template') (cloned)

With a framework

Mount a component into target and unmount it in onCleanup. This is React; the guides show the same for the others.

dashboard: ({ target, props, onCleanup }) => {
  const root = createRoot(target)
  onCleanup(() => root.unmount())
  root.render(<Dashboard id={props.id} />)
}

React · Vue · Svelte · Angular · Orbit CSS

URL views are inserted as HTML and their <script> tags do not run. Put behaviour in a function view, and sanitize HTML that comes from elsewhere.