---
area: "Learn"
parent: "Forms chapter"
url: "https://unpoly.com/learn/watch-options"
---
<nav aria-label="Unpoly docs">[All docs](https://unpoly.com/index.md) · [Forms chapter](https://unpoly.com/learn/forms.md)</nav>

# Watch options

Every feature that watches form fields for changes shares the same options: which events to observe, how long to wait before reacting, and what to show while a change is being processed. You set them as `[up-watch-...]` attributes in HTML, or pass them as options from JavaScript.

The options on this page apply to all of these features:

| HTML | JavaScript | Purpose |
| --- | --- | --- |
| [`[up-watch]`](https://unpoly.com/api/up-watch.md) | [`up.watch()`](https://unpoly.com/api/up.watch.md) | Run a callback after a change |
| [`[up-validate]`](https://unpoly.com/api/up-validate.md) | [`up.validate()`](https://unpoly.com/api/up.validate.md) | Render a new form state after a change |
| [`[up-autosubmit]`](https://unpoly.com/api/up-autosubmit.md) | [`up.autosubmit()`](https://unpoly.com/api/up.autosubmit.md) | Submit a form after a change |
| [`[up-switch]`](https://unpoly.com/api/up-switch.md) |  | Switch other elements after a change |

Options for events and delays apply to all of them. Options for disabling and loading state apply to features that render, like [`[up-validate]`](https://unpoly.com/api/up-validate.md) and [`[up-autosubmit]`](https://unpoly.com/api/up-autosubmit.md).

<nav aria-label="Contents">

#### Contents

- [Which events to watch](#events)
- [Debouncing callbacks](#debouncing)
- [Disabling fields while working](#disabling)
- [Showing loading state while working](#loading-state)
- [Setting options for multiple fields](#multiple-fields)

</nav>

## Which events to watch {#events}

Most features watch the `input` event by default, so they react while the user is typing. Only [validation](https://unpoly.com/api/up-validate.md) watches the `change` event by default, which fires when the user is done editing and leaves the field.

You can control which events are observed by setting an `[up-watch-event]` attribute:

```html
<form action="/search">
  <input name="query" up-autosubmit up-watch-event="change">
</form>
```

From JavaScript you can pass an `{ event }` option instead:

```js
up.autosubmit(field, { event: 'change' })
```

Multiple events can be passed as a space- or comma-separated string, or as an array. For [`up.watch()`](https://unpoly.com/api/up.watch.md), [`[up-autosubmit]`](https://unpoly.com/api/up-autosubmit.md) and [`[up-switch]`](https://unpoly.com/api/up-switch.md), Unpoly guarantees the callback is run only once per unique changed value. [`[up-validate]`](https://unpoly.com/api/up-validate.md) validates on every watched event, so watching `input` also validates once more on `change`.

### Normalizing non-standard events {#normalizing-non-standard-events}

Sometimes fields emit non-standard events instead of `change` and `input`. You can configure Unpoly to normalize field events so they become observable as `change` or `input`.

For example, if a custom select component emits a `myselect:chosen` event on selection:

```js
up.form.config.watchChangeEvents = ['change', 'myselect:chosen']
```

A watcher with `[up-watch-event="change"]` will now also react to a `myselect:chosen` event.

In the same fashion you may configure an event in [`up.form.config.watchInputEvents`](https://unpoly.com/api/up.form.config.md#config.watchInputEvents) to make it observable with `[up-watch-event="input"]`.

Instead of configuring an array of event types, you may also set a function that accepts a form field and returns an array of event types to watch for that field.

For example, on desktop browsers date pickers inconveniently emit a `change` event when any date _component_ changes, causing multiple events as the user picks a day, month and year. In this case we can watch `blur` instead of `change` for such fields:

```js
up.form.config.watchChangeEvents = function(field) {
  if (field.matches('input[type=date]') && isDesktop()) { // isDesktop() is your own check
    return ['blur']
  } else {
    return ['change']
  }
}
```

## Debouncing callbacks {#debouncing}

When observing the `input` event, you may want to wait until the user has stopped typing before running a callback. You can do so by setting an `[up-watch-delay]` attribute:

```html
<form action="/search">
  <!-- Wait until the user has stopped typing for 100 milliseconds -->
  <input name="query" up-autosubmit up-watch-delay="100">
</form>
```

From JavaScript you can pass a `{ delay }` option instead.

For watchers of `input` the default delay is [`up.form.config.watchInputDelay`](https://unpoly.com/api/up.form.config.md#config.watchInputDelay) (which defaults to `0`). For watchers of other events there is no default delay. [`[up-switch]`](https://unpoly.com/api/up-switch.md) is never debounced, because its effects are applied on the client.

If the field's form is [aborted](https://unpoly.com/learn/aborting-requests.md) or destroyed while waiting for a delay, the callback is unscheduled.

> #### Info
>
> Regardless of the delay, Unpoly guarantees that only one async callback is running concurrently. If the form is changed while an async callback is still processing, Unpoly waits until the callback concludes and then re-runs it with the latest field values.

## Disabling fields while working {#disabling}

To prevent user input while processing changes, you can [disable form fields](https://unpoly.com/learn/disabling-forms.md) while an async callback is running.

For this set an `[up-watch-disable]` attribute on the form or field being watched:

```html
<form action="/search">
  <input name="query" up-autosubmit up-watch-disable>
</form>
```

By default, setting `[up-watch-disable]` will cause all fields in the form to be disabled while processing. To [only disable some form controls](https://unpoly.com/learn/disabling-forms.md#disabling-some-controls-only), set the value of `[up-watch-disable]` to any selector that matches fields or buttons.

From JavaScript you can pass a `{ disable }` option instead.

When a callback for [`[up-watch]`](https://unpoly.com/api/up-watch.md) or [`up.watch()`](https://unpoly.com/api/up.watch.md) renders, it must pass these options on. Its third argument holds the options parsed from the field's `[up-watch-...]` attributes. Forward them to the function that renders (see [callback arguments](https://unpoly.com/api/up.watch.md#callback-arguments)):

```js
up.watch('input.query', function(value, name, options) {
  return up.reload('main', { ...options, params: { query: value }})
})
```

> #### Tip
>
> To disable fields while _submitting_ (instead of while watching), use [`[up-disable]`](https://unpoly.com/learn/disabling-forms.md) instead.

## Showing loading state while working {#loading-state}

To signal to users that you're processing changes, you can show arbitrary [loading state](https://unpoly.com/learn/loading-state.md) while an async callback is running.

To apply a [preview](https://unpoly.com/learn/previews.md), set an `[up-watch-preview]` attribute on the form or field being watched:

```html
<form action="/search">
  <input name="query" up-autosubmit up-watch-preview="spinner">
</form>
```

To show a [placeholder](https://unpoly.com/learn/placeholders.md) while working, use an `[up-watch-placeholder]` attribute:

```html
<form action="/search">
  <input name="query" up-autosubmit up-watch-placeholder="#results-placeholder">
</form>
```

From JavaScript you can pass a `{ preview }` or `{ placeholder }` option instead.

While a validation or autosubmit request is loading, [feedback classes](https://unpoly.com/learn/feedback-classes.md) like [`.up-active`](https://unpoly.com/api/up-active.md) and [`.up-loading`](https://unpoly.com/api/up-loading.md) are set by default. To not set them, use an `[up-watch-feedback="false"]` attribute or pass a `{ feedback: false }` option.

## Setting options for multiple fields {#multiple-fields}

Instead of setting `[up-watch-...]` attributes on individual fields, you may also set them on any element containing fields. The [closest](https://developer.mozilla.org/en-US/docs/Web/API/Element/closest) attribute around a changed field is honored.

By setting attributes on the `<form>` you can configure defaults for _all_ watchers:

```html
<form action="/search" up-watch-disable>
  <input name="department" up-autosubmit>
  <input name="query" up-autosubmit>
</form>
```

Form-wide options can be overridden at the field level:

```html
<form action="/search" up-watch-disable>
  <input name="department" up-autosubmit>
  <input name="query" up-autosubmit up-watch-disable="false">
</form>
```

The feature attribute itself can sit on a container, too. Unpoly then watches all fields inside it. This is how you [watch a group of radio buttons](https://unpoly.com/api/up-watch.md#watching-radio-buttons):

```html
<form action="/search">
  <fieldset up-autosubmit up-watch-disable>
    <input type="radio" name="format" value="html"> HTML format
    <input type="radio" name="format" value="pdf"> PDF format
    <input type="radio" name="format" value="txt"> Text format
  </fieldset>
</form>
```

Options passed from JavaScript override all attributes:

```js
up.validate(field, { disable: true })
```

<nav aria-label="Reading order">

- [Previous: Custom form fields](https://unpoly.com/learn/custom-form-fields.md)
- [Next: Overlays](https://unpoly.com/learn/overlays.md)

</nav>

