Watches form fields and runs a callback when a value changes.
While you can also listen to a standard input
event,
using up.watch()
comes with a number of quality of live improvements:
The unobtrusive variant of this is the [up-watch]
attribute.
The following would print to the console whenever an input field changes:
up.watch('input.query', function(value) {
console.log('Query is now', value)
})
The watch callback may accept up to three arguments that describe the observed change:
up.watch('input.query', function(value, name, options) {
console.log('Query is now', value)
})
Here is a full description of the individual callback arguments:
Name | Type | Description |
---|---|---|
value |
string |
The changed field value. |
name |
string |
The [name] of the changed field. |
options.origin |
Element |
The element that caused the change. This is usually the changed field. |
options.feedback |
boolean |
Whether to set feedback classes while working. Parsed from the field's [up-watch-feedback] attribute. |
options.disable |
boolean |
Which fields to disable while working. Parsed from the field's [up-watch-disable] attribute. |
options.preview |
string |
The name of a preview to run while working. Parsed from the field's [up-watch-preview] attribute. |
options.placeholder |
string |
The HTML or selector for a placeholder to show while working. Parsed from the field's [up-watch-placeholder] attribute. |
When rendering from a watch callback, you should forward the options
to the rendering function:
up.watch('input.query', function(value, name, options) { // mark-phrase "options"
return up.reload('main', { ...options, params: { query: value }) // mark-phrase "options"
})
Tip
A rendering watch callback can often be replaced with
[up-autosubmit]
.
Instead of a single form field, you can also pass multiple fields,
a <form>
or any container that contains form fields.
The callback will be run if any of the given fields change:
up.watch('form', function(value, name) {
console.log('The value of %o is now %o', name, value)
})
When your callback does async work (like fetching data over the network) it should return a promise that settles once the work concludes:
up.watch('input.query', function(value, name, options) {
let url = '/search?query=' + escapeURIFragment(value)
return up.render('.results', { url, ...options }) // mark-phrase "return"
})
Unpoly will guarantee that only one async callback is running concurrently. If the form is changed while an async callback is still processing, Unpoly will wait until the callback concludes and then run it again with the latest field values.
You can also return a promise by using async
/ await
:
up.watch('input.query', async function(value, name, options) { // mark-phrase "async"
let url = '/search?query=' + escapeURIFragment(value)
await up.render('.results', { url, ...options }) // mark-phrase "await"
})
You may also pass the { batch: true }
option to receive all
changes since the last callback in a single object:
up.watch('form', { batch: true }, function(diff, options) {
for (let name in diff) {
let value = diff[name]
console.log('The value of %o is now %o', name, value)
}
})
The form field that will be watched.
You can pass a field, a <form>
or any container that contains form fields.
The callback will be run if any of the contained fields change.
If set to true
, the onChange
callback will receive multiple
detected changes in a single diff object as its argument.
The object's keys are the names of the changed fields. The object's values are the values of the changed fields.
The types of event to observe.
The number of milliseconds to wait between an observed event and running the callback.
See debouncing callbacks.
The callback to run when the field's value changes.
The callback is called with arguments that describe the change.
An async callback function must return a promise that settles when the callback completes.
A destructor function that unsubscribes the watcher when called.
Watching will stop automatically when the form is destroyed.