# Refs and forms

Source: https://signy.dev/documentation/1/components/refs-and-forms/

Read input in events, write to fields through refs.

## Events

An attribute named `on` plus the event name adds a listener: `onClick`, `onInput`, `onSubmit`, `onKeyDown`. The name is lowercased, so `onDblClick` listens to `dblclick`.

## Refs

`createRef()` gives an object whose `current` is the element after render. `ref` also takes a callback.

```js
private input = createRef<HTMLInputElement>();

html`<input ref=${this.input} />`;
html`<canvas ref=${(el) => this.draw(el)}></canvas>`;
```

## Forms

Keep state in signals and read the field in its event. To reset a field, set its `value` through a ref. Binding `value=${() => ...}` sets the attribute, which the browser ignores once someone has typed.

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

class Search extends Component {
  query = new Signal("");
  input = createRef();

  clear() {
    this.query.value = "";
    this.input.current.value = "";
    this.input.current.focus();
  }

  render() {
    return html`
      <form role="search" onSubmit=${(e) => e.preventDefault()}>
        <input ref=${this.input} type="search" aria-label="Search"
          onInput=${(e) => (this.query.value = e.currentTarget.value)} />
        <button type="button" class="secondary" onClick=${() => this.clear()}>Clear</button>
      </form>
      <p>Searching for: ${() => this.query.value || "nothing yet"}</p>
    `;
  }
}

application(Search).mount("#forms-search");
```

## Attributes

- A function binds the attribute: `disabled=${() => busy.value}`.
- `true` sets an empty attribute and `false` removes it. For ARIA states, pass a string: `aria-expanded=${() => String(open.value)}`.
- `style` takes a string or an object.
