Vuetify
Map Vuetify inputs to Formhaus field types through the components prop of FormRenderer from @formhaus/vue.
Install
bash
npm install @formhaus/core @formhaus/vue vuetifyComponent map
ts
import type { FieldComponentMap } from '@formhaus/vue';
import AutocompleteField from './fields/AutocompleteField.vue';
import CheckboxField from './fields/CheckboxField.vue';
import FileField from './fields/FileField.vue';
import RadioField from './fields/RadioField.vue';
import SelectField from './fields/SelectField.vue';
import SwitchField from './fields/SwitchField.vue';
import TextField from './fields/TextField.vue';
import TextareaField from './fields/TextareaField.vue';
export const components: Partial<FieldComponentMap> = {
text: TextField,
email: TextField,
phone: TextField,
number: TextField,
password: TextField,
date: TextField,
datetime: TextField,
select: SelectField,
autocomplete: AutocompleteField,
multiselect: SelectField,
checkbox: CheckboxField,
radio: RadioField,
switch: SwitchField,
file: FileField,
textarea: TextareaField,
};Text field
vue
<script setup>
const props = defineProps({
field: { type: Object, required: true },
value: { default: undefined },
error: { type: String, default: undefined },
loading: { type: Boolean, default: false },
disabled: { type: Boolean, default: false },
});
const emit = defineEmits(['update:value', 'blur', 'focus']);
const inputType =
props.field.type === 'email' ? 'email'
: props.field.type === 'password' ? 'password'
: props.field.type === 'number' ? 'number'
: props.field.type === 'date' ? 'date'
: props.field.type === 'datetime' ? 'datetime-local'
: props.field.type === 'phone' ? 'tel'
: 'text';
</script>
<template>
<v-text-field
:id="field.key"
:label="field.label"
:type="inputType"
:model-value="value != null ? String(value) : ''"
:placeholder="field.placeholder"
:error-messages="error ? [error] : []"
:hint="field.helperText"
:persistent-hint="!!field.helperText"
:disabled="disabled || loading"
@update:model-value="(v) => emit('update:value', field.type === 'number' ? Number(v) : v)"
@blur="emit('blur')"
@focus="emit('focus')"
/>
</template>App
vue
<script setup>
import { FormRenderer } from '@formhaus/vue';
import { components } from './component-map';
import FormActions from './actions/FormActions.vue';
import StepProgress from './actions/StepProgress.vue';
import definition from './definition.json';
function onSubmit(values) {
console.log('Submitted:', values);
}
</script>
<template>
<v-app>
<v-container style="max-width: 600px">
<FormRenderer
:definition="definition"
:components="components"
:actions-component="FormActions"
:progress-component="StepProgress"
@submit="onSubmit"
/>
</v-container>
</v-app>
</template>The other renderers are in src/fields and src/actions.
Server re-validation
The example validates in the browser only. To check the same rules on the server, build a FormEngine from the same definition and call validate(), then pass the returned errors to the errors prop. See Nuxt for a complete server route.