24
Components

FormForgeRenderer

Render, navigate, validate, and submit FormForge forms in internal or controlled mode.

FormForgeRenderer renders and can submit a FormForge form.

The component resolves two explicit external paths internally:

  • external model mode (modelValue provided)
  • external schema mode (schema provided)

Internal mode

Pass only a form key and let the component manage load, validation, navigation, and submit.

<FormForgeRenderer :form-key="'contact'" />

Standalone hybrid mode (form-key + v-model)

You can combine form-key with v-model (modelValue) to read form data in real time without final internal submission.

<script setup lang="ts">
const formData = ref<Record<string, unknown>>({})
</script>

<template>
  <FormForgeRenderer
    form-key="my-form"
    v-model="formData"
  />
</template>

When modelValue is provided:

  • the renderer emits update:modelValue on every field change
  • form submit does not trigger backend submission from the renderer
  • submit buttons are hidden
  • internal submit success and error UI states are hidden

This mode is designed for external state management and custom submission flows.

Controlled mode

Use composables and pass model and schema manually.

<FormForgeRenderer
  :schema="form.schema"
  :model-value="form.state"
  :zod-schema="form.zodSchema"
  @update:model-value="form.replaceState"
/>

Progress and navigation

FormForgeRenderer can show the current block progress and the built-in navigation buttons.

  • showProgress renders a UProgress bar when more than one block is visible
  • showSubmit keeps the submit button visible
  • Previous and Next appear when the renderer can navigate between blocks
  • simulation keeps navigation visible in preview-style usage
  • previewPageKey locks the renderer to a single block, which is useful for playground previews
<FormForgeRenderer
  form-key="contact"
  :show-progress="true"
  :simulation="true"
  :preview-page-key="selectedPageKey"
/>

Validation API (standalone and external model)

FormForgeRenderer exposes validation helpers through the component ref:

  • validate(options?)
  • validateField(name)
  • clearErrors(path?)
  • getErrors(path?)
<script setup lang="ts">
const renderer = ref<InstanceType<typeof FormForgeRenderer> | null>(null)

async function runValidation(): Promise<void> {
  const result = await renderer.value?.validate()
  if (!result?.valid) {
    console.log(renderer.value?.getErrors())
  }
}
</script>

<template>
  <FormForgeRenderer ref="renderer" form-key="my-form" />
</template>

Validation props:

  • validateOn
  • validateOnBlur

In external v-model integrations, blur-based validation is handled explicitly per field (focusout path) for more predictable standalone behavior.

Integrating in a custom parent form

When FormForge data is embedded in a parent form, block parent submit until renderer validation passes.

<script setup lang="ts">
import { z } from 'zod'

const renderer = ref<InstanceType<typeof FormForgeRenderer> | null>(null)
const formData = ref<Record<string, unknown>>({})

const parentSchema = z.object({
  title: z.string().min(1),
  data: z.record(z.string(), z.unknown())
})

async function onParentSubmit(): Promise<void> {
  const rendererResult = await renderer.value?.validate()
  if (!rendererResult?.valid) {
    return
  }

  // continue with your external submit flow
}
</script>

<template>
  <form @submit.prevent="onParentSubmit">
    <FormForgeRenderer
      ref="renderer"
      form-key="my-form"
      v-model="formData"
      :validate-on-blur="true"
    />
  </form>
</template>

Use an object schema for embedded FormForge payloads (z.record(...)), not z.string().