FormForgeRenderer
FormForgeRenderer renders and can submit a FormForge form.
The component resolves two explicit external paths internally:
- external model mode (
modelValueprovided) - external schema mode (
schemaprovided)
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:modelValueon every field change - form submit does not trigger backend submission from the renderer
- submit buttons are hidden by default
- internal submit success and error UI states are hidden
This mode is designed for external state management and custom submission flows.
showSubmit uses tri-state behavior:
- omit
show-submitto hide submit buttons automatically when usingv-model - use
:show-submit="true"to show the submit button explicitly - use
:show-submit="false"to keep it hidden explicitly
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.
pagination="auto"keeps the default paginated navigation between visible blockspagination="none"renders all visible fields from all blocks in one viewshowProgressrenders aUProgressbar when more than one block is visibleshowProgressis ignored whenpagination="none"showSubmitcontrols the submit button; it defaults to hidden withv-modeland visible otherwisePreviousandNextappear when the renderer can navigate between blockssimulationkeeps navigation visible in preview-style usagepreviewPageKeylocks 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"
/>
Use pagination="none" when all fields should appear on a single screen:
<FormForgeRenderer
form-key="contact"
pagination="none"
:show-progress="true"
/>
In this mode, navigation controls and the progress indicator are hidden. Validation still covers the full form, the submitted payload remains unchanged, and conditional rules continue to work across blocks.
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:
validateOnvalidateOnBlur
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().