Skip to content

FormBuilder

FormBuilder is the editing component. It displays the catalog, canvas, selected field properties, preview mode and import/export actions.

Basic usage

vue
<script setup lang="ts">
import type { FormKitSchemaDefinition } from '@formkit/core'

const schema = ref<FormKitSchemaDefinition[]>([])
const values = ref<Record<string, unknown>>({})
</script>

<template>
  <ClientOnly>
    <FormBuilder
      builder-id="contact"
      v-model:schema="schema"
      v-model:values="values"
    />
  </ClientOnly>
</template>

ClientOnly is recommended in Nuxt to avoid rendering the visual editor during SSR.

Save

vue
<script setup lang="ts">
import type { FormKitSchemaDefinition } from '@formkit/core'

type SavePayload = {
  builderId: string
  schema: FormKitSchemaDefinition[]
  values: Record<string, unknown>
  settings: Record<string, unknown>
}

const schema = ref<FormKitSchemaDefinition[]>([])
const values = ref<Record<string, unknown>>({})

async function saveForm(payload: SavePayload) {
  await $fetch('/api/forms/contact', {
    method: 'PUT',
    body: payload,
  })
}
</script>

<template>
  <ClientOnly>
    <FormBuilder
      builder-id="contact"
      v-model:schema="schema"
      v-model:values="values"
      autosave
      @save="saveForm"
    />
  </ClientOnly>
</template>

The @save payload contains the data required to render the form with FormViewer.

Responsive drawers

The builder computes drawers from its rendered width. It can be placed in a full page, card, tab or resizable panel.

ModeBehavior
defaultAuto-fit. Drawers become overlays when space is limited.
desktopDrawers remain persistent.
mobileOne overlay drawer at a time.
vue
<FormBuilder
  builder-id="embedded-contact"
  drawer-behavior="default"
  height="720px"
/>

Selection and drag-and-drop

The canvas uses one interaction session for click, selection, drag-and-drop and drop. This avoids synthetic post-drag clicks and keeps selection coherent across catalog, canvas and tree.

data-qform-interaction-phase, data-qform-selected-field and data-qform-drag-source are diagnostic and test attributes.

Reference API

vue
<script setup lang="ts">
import type { FormKitSchemaDefinition } from '@formkit/core'

type FormBuilderPublicApi = {
  save: () => {
    builderId: string
    schema: FormKitSchemaDefinition[]
    values: Record<string, unknown>
    settings: Record<string, unknown>
  }
  reset: () => void
  exportSchema: () => FormKitSchemaDefinition[]
  importSchema: (schema: FormKitSchemaDefinition[]) => void
}

const builderRef = ref<FormBuilderPublicApi | null>(null)

function downloadSchema() {
  const schema = builderRef.value?.exportSchema() ?? []
  const blob = new Blob([JSON.stringify(schema, null, 2)], { type: 'application/json' })
  const url = URL.createObjectURL(blob)
  const anchor = document.createElement('a')
  anchor.href = url
  anchor.download = 'contact.schema.json'
  anchor.click()
  URL.revokeObjectURL(url)
}
</script>

<template>
  <QBtn label="Export" color="primary" @click="downloadSchema" />
  <FormBuilder ref="builderRef" builder-id="contact" />
</template>

Common options

OptionDescription
builder-idStable identifier; required in practice.
v-model:schemaFormKit/Quasar schema produced by the builder.
v-model:valuesPreview values or initial values.
v-model:preview-modeediting or previewing.
autosaveEnables local safety save.
storage-keyExplicit autosave key.
localefr or en.
catalogCustom catalog.
config-panelsCustom settings panels.

See Props, events and API for the full contract.

QForm Builder — Nuxt 4, Quasar and FormKit layer for dynamic forms.