Components
@vuetils/form comes with two helper components UField and UForm that make it easier to create forms. These components handle the two-way data binding and add validation classes to the inputs and the form element so differnt form states can be styled with CSS.
UField
UField is the basic building block of a form. It is a wrapper around the native label element and can be used in the exact same way. UField needs exactly one input element as a slot and can have optional label content too. The label content can either be just plain text like in the example below or any other Vue components or HTML elements.
If used outside a UForm component UField needs a Field instance as a prop.
Validation Classes
Depending on the validation state of the Field instance these classes are added to the input element:
v-valid- added when the field is validv-invalid- added when the field is invalidv-pristine- added when the field's value has not been changed yetv-dirty- added when the field's value has been changedv-pending- added when the field hasasync validatorsthat are being resolvedv-touched- added when the field has been blurred yetv-untouched- added when the field hasn't been blurred yet
There are also the classes v-label and v-input that are added to the label and input elements respectively. Play around with the example and see how different classes get added or removed.
Example
<template>
<UField :field="field">
Label:
<input name="field" type="text" required />
</UField>
</template>
<script setup>
import { UField, required, useField } from '@vuetils/form';
const field = useField('', { validators: [required] });
</script>Markup
This will create the following clean and minimal HTML markup
// model value:
<label class="v-label">
Label:
<input
name="field"
type="text"
required
class="v-invalid v-pristine v-untouched v-input"
/>
</label>UForm
UForm is a wrapper around the native form element and can be used in the exact same way. UForm needs UField components as child slots. The name attribute of the input element is used to bind the input to the matching Field instance.
Validation Classes
Similar how it works with UField these classes are added depending on the validation state of the Form instance:
v-valid- added when all fields are validv-invalid- added when on ore more fields are invalidv-pristine- added when all fields are pristinev-dirty- added when one or more fields are dirtyv-pending- added when one or more fields are pendingv-submitted- added when the form has been submitted no matter if it was valid or notv-touched- added when one or more fields have been blurredv-untouched- added when no fields haven been blurred
There is also the class v-form that is added to the form element. Play around with the example and see how differnt classes get added or removed.
Example
<template>
<UForm :form="form">
<UField>
Firstname:
<input name="firstname" type="text" required />
</UField>
<UField>
Lastname:
<input name="lastname" type="text" required />
</UField>
<button>Submit</button>
</UForm>
</template>
<script setup>
import { UField, UForm, required, useForm } from '@vuetils/form';
const form = useForm({
firstname: ['', [required]],
lastname: ['', [required]],
});
</script>Markup
This will create the following clean and minimal HTML markup
<form class="v-invalid v-pristine v-untouched v-form">
// model value:
<label class="v-label">
Email:
<input
name="firstname"
type="firstname"
required
class="v-invalid v-pristine v-untouched v-input"
/>
</label>
// model value:
<label class="v-label">
Password:
<input
name="lastname"
type="lastname"
required
class="v-invalid v-pristine v-untouched v-input"
/>
</label>
<button>Submit</button>
</form>Submit event
UForm emits the custom event v-submit every time the form is submitted. The event handler receives the current values of the form. This can also be typed with typeof form.values as shown in the example below.
If you want to you can also just listen to the native submit event.
<template>
<UForm :form="form" v-submit="onSubmit">
<!-- Form inputs -->
</UForm>
</template>
<script setup lang="ts">
import { UForm, useForm } from '@vuetils/form';
const form = useForm({
firstname: [''],
lastname: [''],
});
function onSubmit(values: typeof form.values) {
if (form.invalid) {
//handle errors
}
// do something with the values
}
</script>