---
title: "Submit"
description: "Handle AutoForm's submit event, automatic and manual loading, validation errors and programmatic submission."
canonical_url: "https://nuxt.mhaibaraai.cn/en/docs/auto-form/submit"
---
# Submit

> Handle AutoForm's submit event, automatic and manual loading, validation errors and programmatic submission.

## `loadingAuto`

When `@submit` returns a Promise, the submit button loading state is managed automatically by AutoForm (`loadingAuto` is enabled by default):

```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>
```

## Manual Loading Control

Disable `loading-auto` and let `submit-button-props.loading` take over the button state:

```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>
```

## Async Errors and Validation Events

Handle async errors in `@submit`; `@error` receives field validation failures:

```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>
```

## Programmatic Submit

Get the form instance via `useTemplateRef`, then trigger `formRef.submit()`, `reset()`, `clear()` externally (use `:submit="false"` to hide the built-in button):

```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](https://nuxt.mhaibaraai.cn/sitemap.md) for all pages.
