# html templates

Source: https://signy.dev/documentation/1/templates/html-templates/

Markup in a tagged template, turned into real DOM nodes.

`html` is a tagged template built on [htm](https://github.com/developit/htm). It returns DOM nodes, not strings, and runs in the browser with no build step.

## Values

```js
html`<p>${text}</p>`                      // text, set once
html`<p>${() => count.value}</p>`         // text, kept up to date
html`<p>${html`<b>nested</b>`}</p>`       // nodes
```

## Attributes and events

```js
html`
  <input
    type="text"
    class=${() => (invalid.value ? 'invalid' : '')}
    disabled=${() => busy.value}
    onInput=${(e) => (name.value = e.currentTarget.value)} />
`
```

A function value binds the attribute. An `on` attribute with a function adds a listener. `ref` captures the element, see [Refs and forms](https://signy.dev/documentation/1/components/refs-and-forms/index.html.md).

## Components

A component class goes in the tag name position, closed with `</${Card}>` or self closed with `<${Card} />`.

## SVG

Write SVG in a template as you would in HTML. `svg`, `circle`, `path` and the other SVG tags are created in the SVG namespace, and bindings work on their attributes.

```js
const { Component, Signal, application, html } = Signy;

class Dial extends Component {
  value = new Signal(60);

  render() {
    return html`
      <svg width="120" height="120" viewBox="0 0 120 120" role="img" aria-label="Dial">
        <circle cx="60" cy="60" r="50" fill="none" stroke="currentColor" stroke-opacity="0.2" stroke-width="10" />
        <circle cx="60" cy="60" r="50" fill="none" stroke="#9522d0" stroke-width="10"
          stroke-dasharray="314" stroke-dashoffset=${() => 314 - (314 * this.value.value) / 100}
          transform="rotate(-90 60 60)" />
        <text x="60" y="66" text-anchor="middle" font-size="20" fill="currentColor">${() => this.value.value}%</text>
      </svg>
      <input type="range" min="0" max="100" value="60" aria-label="Value"
        onInput=${(e) => (this.value.value = Number(e.currentTarget.value))} />
    `;
  }
}

application(Dial).mount("#svg-example");
```

`a`, `title`, `style` and `script` exist in HTML and SVG and are created as HTML. Inside an SVG, give them `xmlns="http://www.w3.org/2000/svg"`.

## Pitfalls

- Close void elements: `<input />`, `<br />`, `<img />`. Without the slash, the parser treats the rest of the template as their children and rendering fails.
- `${this.count.value}` renders once. Bind `${() => this.count.value}`.
- A function child that returns markup, such as ``${() => ok ? html`...` : null}``, renders an empty text node. Use [`Show`](https://signy.dev/documentation/1/templates/show/index.html.md).
- `.map()` over a signal array renders once. Use [`For`](https://signy.dev/documentation/1/templates/for-and-index/index.html.md).

## Hyperscript

`h(tag, props, ...children)` is the function under `html`, for code that builds nodes without a template.
