A convenience API for reducing code repetition in a Vue application using the FormValidityObserver
.
Creates an enhanced version of the FormValidityObserver
, known as the VueFormValidityObserver
. It accepts the exact same arguments as the FormValidityObserver
's constructor.
An enhanced version of the FormValidityObserver
, designed specifically for Vue applications. It has the same Type Parameters as the FormValidityObserver
. As with the FormValidityObserver
, the type of M
is derived from the renderer
option, and the type of R
is derived from the renderByDefault
option.
The following methods on the VueFormValidityObserver
are the exact same as the methods on the FormValidityObserver
. These methods are bound to the observer instance to allow for safe object destructuring:
observe(form)
unobserve(form)
disconnect()
validateFields(options)
validateField(name, options)
setFieldError(name, message, render)
clearFieldError(name)
A utility function used to simplify the process of setting up and cleaning up a form's FormValidityObserver
. Pass its return value as a ref
to the form that you're validating to automate setup (i.e., the call to observe
) and teardown (i.e., the call to unobserve
).
The novalidate
parameter indicates that the novalidate attribute should be applied to the form
element when JavaScript is available to the client. By default, its value is true
. (For details on why this attribute is significant, see Enabling Accessible Error Messages during Form Submissions.)
Note: If you use this utility, you should not need to call
observe
,unobserve
, ordisconnect
directly.
Example
<template>
<form :ref="autoObserve()">
<!-- Other Elements-->
</form>
</template>
<script setup>
import { createFormValidityObserver } from "@form-observer/vue";
const { autoObserve } = createFormValidityObserver("focusout");
</script>
Remember that autoObserve
is simply a convenience utility for calling observe
and unobserve
automatically. You're free to setup and teardown the FormValidityObserver
manually if you prefer.
An enhanced version of FormValidityObserver.configure
for Vue
. In addition to configuring a field's error messages, it generates the props that should be applied to the field based on the provided arguments.
Note: If the field is only using the configured
defaultErrors
and/or the browser's default error messages, it does not need to beconfigure
d.
The VueValidationErrors<M, E, R>
type is an enhanced version of the core ValidationErrors<M, E, R>
type. Here is how VueValidationErrors
compares to ValidationErrors
.
The following properties on the VueValidationErrors
type accept the exact same values as the corresponding properties on ValidationErrors
type.
badinput
validate
Example
<template>
<form :ref="autoObserve()">
<!-- Note: Accessible <label>s and error containers were omitted from this example. -->
<input v-bind="configure('username', { validate: validateNewUsername })" />
<input name="password" type="password" />
<input v-bind="configure('confirm-password', { validate: validateConfirmPassword })" />
<input type="date" v-bind="configure('date', { badinput: 'Please provide a valid date.' })" />
</form>
</template>
<script setup lang="ts">
import { createFormValidityObserver } from "@form-observer/vue";
const { autoObserve, configure } = createFormValidityObserver("focusout");
function validateConfirmPassword(field: HTMLInputElement): string | void {
const password = field.form?.elements.namedItem("password") as HTMLInputElement;
return field.value === password.value ? undefined : "Passwords do not match.";
}
async function validateNewUsername(field: HTMLInputElement): Promise<string | void> {
const response = await fetch("/api/username-exists", { body: field.value });
const usernameTaken = await response.text();
return usernameTaken === String(true) ? "Username is already taken" : undefined;
}
</script>
All the other properties on the VueValidationErrors
type are enhancements of the corresponding properties on the ValidationErrors
type, so they follow slightly different rules. For clarity, these "other properties" are:
required
minlength
min
maxlength
max
step
type
pattern
The rules are as follows:
1) When a constraint is configured with an ErrorDetails
object, the object must include a value
property specifying the value of the constraint. In this scenario, both the field's constraint value and its error message are configured.
<template>
<form :ref="autoObserve()">
<!-- Note: Accessible <label>s and error containers were omitted from this example. -->
<input v-bind="configure('name', { required: { value: true, message: requiredField, render: true } })" />
<input v-bind="configure('email', { type: { value: 'email', message: 'Email is invalid', render: false } })" />
<input
v-bind="configure('comment', { maxlength: { value: 80, message: 'Comment must be 80 characters or less' } })"
/>
</form>
</template>
<script setup lang="ts">
import { createFormValidityObserver } from "@form-observer/vue";
import type { ValidatableField } from "@form-observer/vue";
const { autoObserve, configure } = createFormValidityObserver("focusout");
const requiredField = (field: ValidatableField) => `<p>${field.labels[0]?.textContent ?? "Field"} is required.</p>`;
</script>
Note: A constraint can only be configured with an error message when you use the object syntax. The exception to this rule is the required
constraint, which allows you to imply a value of true
when you supply an error message value directly to the constraint.
<template>
<form :ref="autoObserve()">
<!-- Note: Accessible <label>s and error containers were omitted from this example. -->
<input v-bind="configure('first-name', { required: requiredField })" />
<input v-bind="configure('last-name', { required: 'Don\'t ignore me...' })" />
<input v-bind="configure('email', { required: { value: true, message: requiredField } })" />
</form>
</template>
<script setup lang="ts">
import { createFormValidityObserver } from "@form-observer/vue";
import type { ValidatableField } from "@form-observer/vue";
const { autoObserve, configure } = createFormValidityObserver("focusout");
const requiredField = (field: ValidatableField) => `${field.labels[0]?.textContent ?? "Field"} is required.`;
</script>
2) When a constraint is configured with a primitive value, then only the field's constraint value is configured. When the constraint is broken, the browser's default error message for that constraint will be displayed.
This syntax only exists for convenience. You are free to use the regular HTML attributes instead if you like.
<template>
<form :ref="autoObserve()">
<!-- Note: Accessible <label>s and error containers were omitted from this example. -->
<input v-bind="configure('email-1', { required: requiredField, type: 'email' })" />
<input v-bind="configure('email-2', { required: requiredField })" type="email" />
<input name="email-3" type="email" required />
</form>
</template>
<script setup lang="ts">
import { createFormValidityObserver } from "@form-observer/vue";
import type { ValidatableField } from "@form-observer/vue";
const { autoObserve, configure } = createFormValidityObserver("focusout");
const requiredField = (field: ValidatableField) => `${field.labels[0]?.textContent ?? "Field"} is required.`;
</script>
The return type of configure
is simply an object containing the props that should be applied to the configured field. In addition to the field's name
, this object will include any validation props that were configured by the function (e.g., required
, min
, pattern
, etc.).