Skip to content

Vue ​

The Vue adapter renders definitions with Formisch and your own components. It reads the definition, connects every field to Formisch and turns input into the values the schema expects, but renders nothing of its own. Below you will learn how to set it up.

Installation ​

sh
npm install @whatsaaaa/form-builder-vue @whatsaaaa/form-builder-schema @formisch/vue valibot
sh
pnpm add @whatsaaaa/form-builder-vue @whatsaaaa/form-builder-schema @formisch/vue valibot
sh
yarn add @whatsaaaa/form-builder-vue @whatsaaaa/form-builder-schema @formisch/vue valibot
sh
bun add @whatsaaaa/form-builder-vue @whatsaaaa/form-builder-schema @formisch/vue valibot

Vue 3.5.2, @formisch/vue 1.1.1 and Valibot 1.4.1 or later are required. @whatsaaaa/form-builder-schema is a peer dependency, so install it too: the adapter and your code share its one copy, with the createSchemaBuilder and types your code imports.

Usage ​

useJsonForm builds the schema and the initial input, and creates the Formisch form. <JsonFields> renders its fields inside Formisch's <Form>, each with your component for its type:

vue
<script setup lang="ts">
import { Form } from '@formisch/vue'
import type { JsonForm } from '@whatsaaaa/form-builder-schema'
import { JsonFields, useJsonForm } from '@whatsaaaa/form-builder-vue'
import { components } from './fields'

const { definition } = defineProps<{ definition: JsonForm }>()

const jsonForm = useJsonForm(definition, { components })

function save(output: unknown) {
  // { email: 'jane@example.com', password: 'correct horse', newsletter: true }
  console.log(output)
}
</script>

<template>
  <Form :of="jsonForm.form" @submit="save">
    <JsonFields :of="jsonForm" />
    <button type="submit">Sign up</button>
  </Form>
</template>
  • jsonForm.form is a normal Formisch form, so every Formisch method works on it, like reset and setInput.
  • The form element, the submit button and anything around them are yours.
  • A definition with issues throws the builder's DefinitionError. Run validate() first when the definition comes from outside your code.
  • The definition is read once, when the component sets up. To show another one, give the component that calls useJsonForm a new :key.

Options ​

useJsonForm takes the builder, your components, and Formisch's validation modes:

ts
const jsonForm = useJsonForm(definition, {
  // Your own types, rules, messages and extensions. Defaults to createSchemaBuilder().
  builder: createSchemaBuilder({ extensions: [affects()] }),
  // Your component for each field type.
  components,
  // Your component for each layout type.
  layoutComponents: { section: LayoutSection, row: LayoutRow },
  // When a field is validated the first time, and again after that, as in Formisch.
  validate: 'blur',
  revalidate: 'input',
})

Pass a builder when your definitions use your own types, rules or messages, or the conditions of the affects package. components and layoutComponents can also go to <JsonFields> and <JsonField> as props, which win over the options.

Not included ​

  • Labels and display text reach your components as written in the definition. The builder's resolveMessage only changes what goes into the schema, so translate field.label in your components.
  • ui.widget doesn't pick a component. A component can read field.ui itself, like a multiselect that shows checkboxes.

Next steps ​

Continue to field components to write a component for every field type.