---
title: "Form"
description: "Render a native form element wired to a useForm instance for submit and reset."
canonical_url: "https://notformdocs.vercel.app/docs/components/form"
---

> Index of every page on this site: [llms.txt](https://notformdocs.vercel.app/llms.txt)

`Form` renders a native `<form>` and connects it to the instance returned by `useForm`. It is a thin wrapper: it adds no validation of its own.

## Usage

```vue
<script setup lang="ts">
import { Form, useForm } from 'notform'
import { z } from 'zod'

const form = useForm({
  initialValues: { email: '' },
  onSubmit: (data) => {
    return console.log(data)
  },
  schema: z.object({ email: z.email() }),
})
</script>

<template>
  <Form
    :form="form"
    novalidate
    class="stack"
  >
    <!-- fields -->
    <button
      type="submit"
      :disabled="form.isSubmitting"
    >
      Submit
    </button>

    <button type="reset">
      Reset
    </button>
  </Form>
</template>
```

## Props

<field-group>
<field :required="true" name="form" type="UseFormInstance<TSchema>">

The form instance returned by `useForm`.

</field>
</field-group>

## Slots

<table>
<thead>
  <tr>
    <th>
      Slot
    </th>
    
    <th>
      Props
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        default
      </code>
    </td>
    
    <td>
      none
    </td>
    
    <td>
      The form's contents. Read state from the <code>
        form
      </code>
      
       instance you created.
    </td>
  </tr>
</tbody>
</table>

## Behavior

<table>
<thead>
  <tr>
    <th>
      Native event
    </th>
    
    <th>
      What <code>
        Form
      </code>
      
       does
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        submit
      </code>
    </td>
    
    <td>
      Calls <code>
        form.submit(event)
      </code>
      
      , which prevents the browser's page navigation, validates the whole form, and calls <code>
        onSubmit
      </code>
      
       only when valid.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        reset
      </code>
    </td>
    
    <td>
      Prevents the browser's native value reset and calls <code>
        form.reset()
      </code>
      
      , restoring the baseline values and errors.
    </td>
  </tr>
</tbody>
</table>

## Attributes

Attributes such as `id`, `class`, `novalidate`, and `aria-*` are forwarded to the native `<form>` element. Add `novalidate` when you want your schema, not the browser, to produce validation messages.

## Form does not provide context

`Form` does not share the form instance with descendants, and fields do not look it up. Create each field from the instance and pass it explicitly:

```vue
<template>
  <Form :form>
    <Field
      v-slot="{ field }"
      :field="form.field('email')"
    >
      ...
    </Field>

    <ArrayField
      v-slot="{ arrayField }"
      :array-field="form.arrayField('tags')"
    >
      ...
    </ArrayField>
  </Form>
</template>
```

This is what keeps every field fully typed. It also means a field can be created and used anywhere, including outside `Form`.

## Using a plain form element

`Form` is optional. A native `<form>` with two handlers is equivalent:

```vue
<form @submit="form.submit" @reset.prevent="form.reset">
  <!-- fields -->
</form>
```

## Related

- [Submission and reset](https://notformdocs.vercel.app/docs/guides/submission-and-reset)
- [useForm](https://notformdocs.vercel.app/docs/composables/use-form)

## Sitemap

See the full [sitemap](https://notformdocs.vercel.app/sitemap.md) for all pages.
