Skip to content

Form

TIP

Before proceeding with Form, learn first about ModelGroup.

Basic Usage

vue
<script setup>
import { shallowRef } from 'vue'
import { ModelGroup } from '@vrgl/vergil'
import { Form, InputText, Button } from '@vrgl/vergil/components'

const form = new ModelGroup({
	username: {
		value: '',
		validator(value, error) {
			if (!value) error('Username required')
		}
	}
})

const loader = shallowRef(false)
async function handleSubmit(event, payload) {
	loader.value = true
	try {
		await new Promise(r => setTimeout(r, 2000))
		form.reset()
	} finally {
		loader.value = false
	}
}
</script>

<template>
    <Form :fields="form" @submit="handleSubmit">
		<InputText v-model="form.username" label="Username" show-errors :disabled="loader"/>
		<template #submit>
			<Button label="Submit" :loading="loader"/>
		</template>
	</Form>
</template>

<style scoped>
.form {
	width: 220px;
}
</style>

Description

The Form component is a wrapper for a form HTML element, and must receive a ModelGroup instance through its fields prop.

Whenever a Form's underlying form element is submitted (i.e., its submit event is fired), that Form's model group validation is automatically performed with debouncing.

The Form component also manages an internal form-level error which can be set with an exposed setFormError function.

Props

Fields
fields: ModelGroup
required

A ModelGroup instance.

vue
<script setup>
const form = new ModelGroup({
	field: { /* ... */ }
})
</script>

<template>
    <Form :fields="form">
		<!-- ... -->
	</Form>
</template>

Validation Cooldown
validation-cooldown: number = 350

The validation-cooldown prop is the minimum delay in milliseconds to wait before validating a Form's model group since the form element was last submitted (see Description).

Show errors
show-errors: boolean | string[]

Similar to the show-errors prop of some form field components, a Form's show-errors prop allows to display the provided ModelGroup's errors in a Badge component placed after the form fields and before the submit button (see Anatomy).

When show-errors is set to true, the errors of all ModelGroup's nested models will be displayed. In addition, only errors of specific models may be displayed by passing an array of the ModelGroup's dot-notation path strings to those models.

To illustrate, consider the following model group.

js
const form = new ModelGroup({
	foo: { /* ... */ },
	bar: ModelGroup.nested({
		baz: { /* ... */ },
		qux: ModelGroup.nested({ /* ... */ }) 
	})
})

In order to display only the errors of the form.foo and form.bar.baz models, show-errors may be set to ['foo', 'bar.baz'].

Furthermore, a show-errors array may also include paths to nested model groups as long as they are suffixed with a wildcard. Available wildcards are '.*' and '.**', which respectively display all child and descendant models of a nested model group.

Thus, recalling the previous example, the show-errors array ['bar.*'] would display the errors of the form.bar.baz model. Similarly, besides form.bar.baz, the array ['bar.**'] would also include all nested models of the form.bar.qux model group.

Finally, errors are displayed under a heading or label to identify the model (field) they belong to. This label may be customized by providing an special formLabel property to a model group's model specification object.

vue
<script setup>
const form = new ModelGroup({
	check: {
		value: false,
		formLabel: 'Checkbox field',
		validator(value, error) {
			if (!value) error('Must be checked')
		}
	}
})
</script>

<template>
    <Form :fields="form" show-errors>
		<Checkbox v-model="form.check" label="Check"/>
		<template #submit>
			<Button label="Submit"/>
		</template>
	</Form>
</template>

Badge props
badge-props: Record<string, unknown>

Props for the underlying Badge component where model errors are displayed.

Events

After a Form's model group is automatically validated, either the submit or invalid event is emitted depending on the validation result; if no errors are encountered, submit is emitted, and invalid otherwise. Both events accept two parameters: the submit event object and the validated model group's payload.

Submit
onSubmit: (event: Event, payload: ModelGroupPayload) => void

vue
<script setup>
function handleSubmit(event, payload) {
	/* ... */
}
</script>

<template>
    <Form @submit="handleSubmit"/>
</template>

Invalid
onInvalid: (event: Event, payload: ModelGroupPayload) => void

vue
<script setup>
function onInvalid(event, payload) {
	/* ... */
}
</script>

<template>
    <Form @invalid="onInvalid"/>
</template>

Exposed

setFormError

Function to set a form-level error. It receives as a single argument an error message string which is displayed in the Form's error badge. The form error is automatically cleared after some field changes. In addition, the submit slot receives a hasFormError boolean prop which could be used to disable the submit button while there is a form error.

It is recommended to set form-level errors after the form's payload has been validated; for instance, inside the submit event handler.

vue
<script setup lang="ts">
import { ModelGroup, useExposed } from '@vrgl/vergil'

const formExposed = useExposed() as { setFormError: (error: string) => void }
const form = new ModelGroup({
	field: {
		value: ''
	}
})

function handleSubmit(event: SubmitEvent, payload: { field: string }) {
	if (payload.name === '') {
		formExposed.setFormError('Field unchanged')
	}
}
</script>

<template>
    <Form :fields="form" @submit="handleSubmit" :exposed="formExposed" show-errors>
		<InputText v-model="form.field" label="Field"/>
		<template #submit="{ hasFormError }">
			<Button label="Submit" :disabled="hasFormError"/>
		</template>
	</Form>
</template>

Anatomy

<form.form/>

<div.form-fields/>

<slot name="default"/>

<Badge.form-errors/>

<slot name="submit"/>

API Reference

Props

proptypedefault
fieldsModelGroup
validationCooldownnumber350
showErrorsboolean | string[]
badgePropsRecord<string, unknown>

Configuration options

Form's configuration options allow to overwrite some Form props' default values and may be overwritten under the form root-level configuration option.

form.<option>typedefaultglobal
validationCooldownnumber