Either install @myparcel/vue-form-builder
via your favorite package manager, or include the CDN script tag in your HTML.
Yarn
yarn add @myparcel/vue-form-builder
NPM
npm install @myparcel/vue-form-builder
pnpm
pnpm add @myparcel/vue-form-builder
<script src="https://unpkg.com/browse/@myparcel/vue-form-builder"></script>
myForm.js
import {defineForm} from '@myparcel/vue-form-builder';
export const myForm = defineForm('my-form', {
fields: [
// Your fields
],
});
See defining fields for more information about fields.
MyComponent.vue
<template>
<MagicForm
:form="form"
@submit="onSubmit" />
</template>
<script>
import {MagicForm} from '@myparcel/vue-form-builder';
import {myForm} from './myForm';
export default defineComponent({
components: {
MagicForm,
},
setup: () => {
return {
myForm,
};
},
});
</script>
A form is defined using the defineForm
function. This function takes two arguments:
- The name of the form
- An object with the following properties:
fields
: An array of fields
A field is defined using the defineField
function. This function takes one argument; an object with the following properties:
Required
component
: The component to use for the field
Optional
name
: The name of the fieldprops
: The props to pass to the component- One of the following:
validator
: A function that takes the value of the field and returns a boolean. This goes together with the propertyerrorMessage
.validators
: An array of validatorsisValid
: A computed ref that returns a boolean
Fields are categorized into two types based on the passed options:
plainElement
: A field that is not a form element and may have a [name].interactiveElement
: A field with a [name] and a ref to hold a reactive value.
import {defineField} from '@myparcel/vue-form-builder';
const emailField = defineField({
name: 'email',
ref: ref(''),
component: 'input',
props: {
type: 'email',
},
});
To make a field reactive, you need to pass a name and a ref to the field. This ref will be used to hold the value of the field. The type of the ref will be used to determine the type of the field.
import {ref} from 'vue';
const emailField = defineField({
name: 'firstName',
component: 'input',
ref: ref(''), // this is your ref
});
Plain elements are components that are not form elements and do not have a [name]. They are used to create custom fields.
onClick
: Called when the field emits aclick
event
onInput
: Called when the field emits aninput
eventonBlur
: Called when the field emits ablur
eventonFocus
: Called when the field emits afocus
event
You can use the following Vue hooks to hook into the lifecycle of a field:
onCreated
onActivated
onBeforeMount
onBeforeUnmount
onBeforeUpdate
onDeactivated
onMounted
onUnmounted
onUpdated
Please refer to the Vue Options Lifecycle documentation for more information on how these hooks work.
A Validator object looks like this:
import {Validator} from '@myparcel/vue-form-builder';
const validator: Validator = {
validate: (instance, value) => true,
errorMessage:
'This message is added to field.errors when the validator returns false',
};
The validate
function takes two arguments:
- The instance of the field: Field
- The value of the field
You can pass validator(s) in three different ways:
validator
+errorMessage
validators
isValid
validate
If you only have one validator, you can choose to pass it directly to the field:
import {defineField} from '@myparcel/vue-form-builder';
import {ref} from 'vue';
const myField = defineField({
name: 'myField',
component: 'input',
ref: ref(20),
validate: (instance, value) => value > 10,
errorMessage:
'This message is added to field.errors when the validator returns false',
});
validators
Multiple validators can be passed like this, an array of Validator objects:
import {defineField} from '@myparcel/vue-form-builder';
import {ref} from 'vue';
const myField = defineField({
name: 'myField',
component: 'input',
ref: ref(''),
validators: [
{
validate: (instance, value) => !value.toloLowerCase() === value,
errorMessage: 'You must use at least one capital letter.',
},
{
validate: (instance, value) => !value.includes('e'),
errorMessage:
'The most common letter in the English language is not allowed, please be more creative.',
},
],
});
validator precedence
In order to define specific validation functions, a precedence
integer can be passed to a validator function to denote the priority of the validation to trigger, in order. This prevents from showing too many validation warnings at once, when they are not relevant (yet). Best shown in the following example:
import {defineField} from '@myparcel/vue-form-builder';
import {ref} from 'vue';
const myField = defineField({
name: 'email',
component: 'input',
ref: ref(''),
validators: [
{
precedence: 1,
validate: (instance, value) => validateEmail(value),
errorMessage: 'The e-mail address is invalid',
},
{
precedence: 2,
validate: (field, value) => !String(value).includes('john.mack'),
errorMessage: 'We do not send to John Mack',
},
],
});
In the example, in order: the following errors are triggered:
- (no input) => Field is required
- ('a') => The e-mail address is invalid
- ('[email protected]') => We do not send to John Mack
This way, error nr 3 is not shown until error 2 is resolved, which is not shown until error 1 is resolved.
isValid
The isValid
property accepts a computed ref that returns a boolean. This is useful when you want to use a computed property to determine the validity of the field.
import {defineField} from '@myparcel/vue-form-builder';
import {computed, ref} from 'vue';
const myField = defineField({
name: 'myField',
component: 'input',
ref: ref(''),
isValid: computed(() => {
return !myField.value.includes('e');
}),
});
This library is written in TypeScript and has full support for it. You can use the types in your own code to get the best possible experience.
import {defineForm, defineField} from '@myparcel/vue-form-builder';
defineField({
name: 'amount',
component: 'input',
ref: ref(1),
validate: (
instance, // The wrapping form instance
value, // Inferred from the type of ref: number
) => value.length > 0,
});