---
title: "提交"
description: "处理 AutoForm 的提交事件、自动与手动 loading、校验错误以及编程式提交。"
seo_title: "Submit"
seo_description: "Handle AutoForm submission — automatic and manual loading, async errors and validation events, and programmatic submit/reset/clear via the exposed API."
canonical_url: "https://nuxt.mhaibaraai.cn/docs/auto-form/submit"
---
# 提交

> 处理 AutoForm 的提交事件、自动与手动 loading、校验错误以及编程式提交。

## `loadingAuto`

`@submit` 返回 Promise 时，提交按钮的 loading 由 AutoForm 自动管理（`loadingAuto` 默认开启）：

```vue [AutoFormSubmitAutoExample.vue]
<script setup lang="ts">
import type { z } from 'zod'

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

const schema = afz.object({
  name: afz.string().min(2).meta({ label: '姓名' })
})
const state = reactive<Partial<z.output<typeof schema>>>({})

async function onSubmit() {
  await new Promise(r => setTimeout(r, 1500))
  toast.add({ title: '提交成功', description: 'loadingAuto 自动维护按钮 loading', color: 'success' })
}
</script>

<template>
  <MAutoForm :schema="schema" :state="state" @submit="onSubmit" />
</template>
```

## 手动 loading 控制

关闭 `loading-auto`，由 `submit-button-props.loading` 接管按钮状态：

```vue [AutoFormSubmitManualExample.vue]
<script setup lang="ts">
import type { z } from 'zod'

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

const schema = afz.object({
  name: afz.string().min(2).meta({ label: '姓名' })
})
const state = reactive<Partial<z.output<typeof schema>>>({})
const loading = ref(false)

async function onSubmit() {
  loading.value = true
  try {
    await new Promise(r => setTimeout(r, 1500))
    toast.add({ title: '提交成功（手动 loading）', color: 'success' })
  }
  finally {
    loading.value = false
  }
}
</script>

<template>
  <MAutoForm
    :schema="schema"
    :state="state"
    :loading-auto="false"
    :submit-button-props="{ loading, label: loading ? '提交中…' : '提交' }"
    @submit="onSubmit"
  />
</template>
```

## 异常与校验事件

`@submit` 中处理异步异常；`@error` 接收字段校验失败：

```vue [AutoFormSubmitErrorExample.vue]
<script setup lang="ts">
import type { z } from 'zod'

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

const schema = afz.object({
  name: afz.string().min(2).meta({ label: '姓名（最少 2 个字符）' })
})
const state = reactive<Partial<z.output<typeof schema>>>({})

async function onSubmit() {
  try {
    await new Promise((_, reject) => setTimeout(() => reject(new Error('API 返回 500')), 1000))
  }
  catch (e: unknown) {
    const msg = e instanceof Error ? e.message : '未知错误'
    toast.add({ title: '提交失败', description: msg, color: 'error' })
  }
}
function onError() {
  toast.add({ title: '校验未通过', description: '请检查字段输入', color: 'warning' })
}
</script>

<template>
  <MAutoForm :schema="schema" :state="state" @submit="onSubmit" @error="onError" />
</template>
```

## 编程式提交

通过 `useTemplateRef` 拿到表单实例后，可在外部触发 `formRef.submit()`、`reset()`、`clear()`（配合 `:submit="false"` 隐藏内置按钮）：

```vue [AutoFormSubmitRefExample.vue]
<script setup lang="ts">
import type { z } from 'zod'

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

const schema = afz.object({
  name: afz.string().min(2).meta({ label: '姓名' }).default('默认值'),
  age: afz.number().min(0).meta({ label: '年龄' })
})
const state = reactive<Partial<z.output<typeof schema>>>({})
const apiForm = useTemplateRef('apiForm')

async function onSubmit() {
  await new Promise(r => setTimeout(r, 600))
  toast.add({ title: '通过暴露 API 提交成功', color: 'success' })
}
</script>

<template>
  <div class="flex flex-col gap-3">
    <div class="flex flex-wrap gap-2">
      <UButton size="sm" label="submit()" @click="apiForm?.formRef?.submit()" />
      <UButton size="sm" variant="soft" label="reset()" @click="apiForm?.reset()" />
      <UButton size="sm" variant="soft" color="neutral" label="clear()" @click="apiForm?.clear()" />
    </div>
    <MAutoForm ref="apiForm" :schema="schema" :state="state" :submit="false" @submit="onSubmit" />
  </div>
</template>
```


## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
