24
Components

FormForgeRenderer

Render and optionally submit 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 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/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"
/>

Schema resolution priority

  • if schema is provided, it is used directly
  • otherwise, schema is loaded from form-key

Typical features

  • progress display
  • validation alerts
  • submitted and error events

Validation API (standalone and external model)

FormForgeRenderer now 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().