表单级插槽

View source
表单插槽用于自定义表单的整体结构,包括顶部、底部和提交按钮区域。

可用插槽

NameDescription
header表单顶部区域
footer表单底部区域
submit提交区域

在表单字段上方添加自定义内容,适用于显示表单标题、说明文案或警告信息:

欢迎注册
请填写以下信息完成注册,所有字段均为必填项
<script lang="ts" setup>
import type { FormSubmitEvent } from '@nuxt/ui'
import type { z } from 'zod/v4'

const toast = useToast()
const { afz } = useAutoForm()

const schema = afz.object({
  username: afz.string().min(3).meta({ label: '用户名' }),
  email: afz.email().meta({ label: '邮箱' }),
  age: afz.number().min(18).meta({ label: '年龄' })
})

type Schema = z.output<typeof schema>

const form = ref<Partial<Schema>>({})

async function onSubmit(event: FormSubmitEvent<Schema>) {
  toast.add({
    title: '提交成功',
    color: 'success',
    description: JSON.stringify(event.data, null, 2)
  })
}
</script>

<template>
  <UCard>
    <MAutoForm :schema="schema" :state="form" @submit="onSubmit">
      <template #header>
        <UAlert
          color="primary"
          variant="subtle"
          icon="i-lucide-info"
          title="欢迎注册"
          description="请填写以下信息完成注册,所有字段均为必填项"
          class="mb-6"
        />
      </template>
    </MAutoForm>
  </UCard>
</template>

在表单字段下方、提交按钮上方添加自定义内容,适用于显示表单统计、进度信息或额外说明:

表单完成度0 / 2
<script lang="ts" setup>
import type { FormSubmitEvent } from '@nuxt/ui'
import type { z } from 'zod/v4'

const toast = useToast()
const { afz } = useAutoForm()

const schema = afz.object({
  username: afz.string().min(3).meta({ label: '用户名' }),
  role: afz.enum(['admin', 'user', 'guest']).meta({ label: '角色' })
})

type Schema = z.output<typeof schema>

const form = ref<Partial<Schema>>({})

async function onSubmit(event: FormSubmitEvent<Schema>) {
  toast.add({
    title: '提交成功',
    color: 'success',
    description: JSON.stringify(event.data, null, 2)
  })
}
</script>

<template>
  <UCard>
    <MAutoForm :schema="schema" :state="form" @submit="onSubmit">
      <template #footer="{ state }">
        <UCard class="mt-6">
          <div class="flex items-center justify-between text-sm mb-2">
            <span class="text-gray-600 dark:text-gray-400">表单完成度</span>
            <UBadge color="primary" variant="subtle">
              {{ Object.keys(state).filter(k => state[k as keyof Schema]).length }} / {{
                Object.keys(schema.shape).length }}
            </UBadge>
          </div>
          <UProgress
            :value="(Object.keys(state).filter(k => state[k as keyof Schema]).length / Object.keys(schema.shape).length) * 100"
            color="primary"
          />
        </UCard>
      </template>
    </MAutoForm>
  </UCard>
</template>

submit

完全控制提交按钮及其周围的逻辑和 UI,适用于实现多步骤提交、自定义按钮组或条件提交逻辑。

使用此插槽时,需要设置 :submit-button="false" 禁用默认按钮。
表单准备就绪
已填写 0 / 4 字段
<script lang="ts" setup>
import { sleep } from '@movk/core'
import type { FormSubmitEvent } from '@nuxt/ui'
import type { z } from 'zod/v4'

const toast = useToast()
const { afz } = useAutoForm()
const autoForm = useTemplateRef('autoForm')

const schema = afz.object({
  username: afz.string().min(3, '用户名至少 3 个字符').meta({ label: '用户名' }),
  email: afz.email('请输入有效的邮箱地址').default('test@example.com').meta({ label: '邮箱' }),
  password: afz.string({ type: 'withPasswordToggle' }).min(8, '密码至少 8 个字符').meta({ label: '密码' }),
  agreeToTerms: afz.boolean({ controlProps: { label: '我同意服务条款和隐私政策' } }).meta({ label: '同意条款' })
})

type Schema = z.output<typeof schema>

const form = ref<Partial<Schema>>({})
const isSubmitting = ref(false)

function clearForm() {
  autoForm.value?.clear()
}

function resetForm() {
  autoForm.value?.reset()
}

async function onSubmit(event: FormSubmitEvent<Schema>) {
  isSubmitting.value = true
  await sleep(2000)

  toast.add({
    title: '提交成功',
    color: 'success',
    description: JSON.stringify(event.data, null, 2)
  })

  isSubmitting.value = false
}
</script>

<template>
  <UCard>
    <MAutoForm
      ref="autoForm"
      :schema="schema"
      :state="form"
      :submit-button="false"
      @submit="onSubmit"
    >
      <template #submit="{ loading, errors, fields, state }">
        <div class="space-y-4">
          <div class="flex items-center justify-between p-4 bg-gray-50 dark:bg-gray-800 rounded-lg">
            <div class="flex items-center gap-2">
              <UIcon
                :name="Object.keys(errors).length > 0 ? 'i-lucide-circle-alert' : 'i-lucide-circle-check'"
                :class="Object.keys(errors).length > 0 ? 'text-red-500' : 'text-green-500'"
              />
              <span class="text-sm font-medium">
                {{ Object.keys(errors).length > 0 ? '请修复表单错误' : '表单准备就绪' }}
              </span>
            </div>

            <div class="text-xs text-gray-500 dark:text-gray-400">
              已填写 {{ Object.keys(state).filter(k => state[k as keyof Schema] !== undefined && state[k as keyof Schema]
                !== '').length }} / {{ fields.length }} 字段
            </div>
          </div>

          <div class="flex gap-3">
            <UButton
              type="submit"
              :loading="loading || isSubmitting"
              color="primary"
              size="lg"
              icon="i-lucide-user-plus"
              :disabled="!form.agreeToTerms"
            >
              {{ loading || isSubmitting ? '正在注册...' : '创建账户' }}
            </UButton>

            <UButton
              type="button"
              variant="outline"
              color="neutral"
              size="lg"
              icon="i-lucide-rotate-ccw"
              @click="resetForm()"
            >
              重置
            </UButton>

            <UButton
              type="button"
              variant="outline"
              color="neutral"
              size="lg"
              icon="i-lucide-eraser"
              @click="clearForm()"
            >
              清空
            </UButton>
          </div>

          <UAlert
            v-if="Object.keys(errors).length > 0"
            color="error"
            variant="subtle"
            icon="i-lucide-triangle-alert"
            title="表单验证失败"
          >
            <template #description>
              <ul class="mt-2 space-y-1">
                <li v-for="(error, field) in errors" :key="field" class="text-sm">
{{ error }}
                </li>
              </ul>
            </template>
          </UAlert>
        </div>
      </template>
    </MAutoForm>
  </UCard>
</template>

API

插槽参数

NameTypeDescription
errorsFormError[]表单所有错误列表
loadingboolean表单提交加载状态
fieldsAutoFormField[]字段配置列表
stateFormState表单当前状态
Copyright © 2025 - 2025 YiXuan - MIT License