Webapp

An app that runs in the browser, like these docs do: two counters, each a button that adds to its own count. There's no server involved. The program is built for the browser, and the page updates itself as you click.

A component

@component makes Counter a piece of the page with its own state. It's still an ordinary struct, with an ordinary render method that returns its markup as Html. Which fields do what is marked on the fields themselves:

  • count is marked @state. Setting it - set self.count += self.step - renders the counter again, and only this counter.
  • step isn't, so it's fixed once the counter is made. That's how the page passes each counter its settings: Counter{step := 10}.

Events

Inside #HTML, an event attribute like onclick takes a lambda through #{ }, called each time the event fires. Here it calls increment, which changes the state, which renders the counter again. There's no event object to unpack and no DOM to update by hand.

The app

@app(mount := "#app") plays the part @main plays in a program. The folder is built for the browser, and once the page loads, main is called and its result goes into the element #app selects. The page needs nothing but that element and the built script.

main puts two counters into the page with #{ Counter{} }. Putting a component into #HTML this way is what makes it live: each one keeps its own count and renders on its own. Calling Counter{}.render() instead would only insert a snapshot of its markup.

Testing without a browser

A component is a struct with methods, so tests use it directly. The first test calls increment and reads count, and the second renders the counter and looks at the text. Neither needs a browser, a page, or a click.

Concepts shown

  • @app as a browser app's entry point.
  • Components with @component, and state with @state.
  • Settings passed to a component through its other fields.
  • Event handlers as lambdas in #HTML.
  • Testing a component by calling its methods.