NotForm
<NotForm> is the root component that wraps your form. It provides the form instance to all descendant field components via Vue's provide/inject, so you don't need to pass a form prop to every <NotField> and <NotArrayField> individually, and it wires up the native submit and reset events on your behalf.
<NotForm> is a convenience, not a requirement. Every field component also accepts an explicit form prop, which takes priority over <NotForm>'s context and is required if you render fields without a <NotForm> ancestor at all.Under the hood, <NotForm> renders a native <form> element, and it automatically:
- Prevents the browser's default full-page navigation on
submitand default field-clearing onreset— both would otherwise happen before any of your own logic runs, so this hands control back to you. - Provides the
forminstance to descendant<NotField>and<NotArrayField>components.
Because the underlying element is native, it does not clear validation errors or restore values by itself — that's what form.reset() does. <NotForm> only stops the browser from doing its own, separate reset first. This is why the usage example below still binds @submit="form.submit" and @reset="form.reset()" explicitly: <NotForm> clears the way for those calls to run, but doesn't make them for you.
Because it's still a real <form> element, other native behavior keeps working as expected:
- Native form attributes like
action,method, andenctypecan be set directly on<NotForm>and pass through. - Submitting with the keyboard (pressing Enter in a text field) and assistive technology both work the same as with a plain
<form>. - Native HTML validation attributes (
required,pattern,minlength, and so on) still trigger the browser's built-in validation UI alongside NotForm's own. If you only want NotForm's validation messages to show, addnovalidateto suppress the browser's.
Usage
A typical form setup involves passing a form instance to <NotForm> via the form prop, then wrapping your fields in its default slot.
<script setup lang="ts">
import { NotForm, useNotForm } from 'notform'
import { z } from 'zod'
const schema = z.object({
email: z.email('Invalid email'),
password: z.string().min(8, 'Password must be at least 8 characters'),
})
const form = useNotForm({
onSubmit(values) {
console.log('Form submitted:', values)
},
schema,
})
</script>
<template>
<NotForm
:form="form"
@submit="form.submit"
@reset="form.reset()"
>
<!-- Form fields go here -->
<button
type="submit"
:disabled="form.isSubmitting"
>
Submit
</button>
<button type="reset">
Reset
</button>
</NotForm>
</template>
API
Props
This is the same instance returned by
useNotForm. <NotForm> makes it available to every <NotField> and <NotArrayField> beneath it, without needing to repeat it as a prop on each one.Slots
default
The default slot for housing your form fields.
<template>
<NotForm
:form="form"
@submit="form.submit"
@reset="form.reset()"
>
<!-- Form fields go here -->
</NotForm>
</template>
<NotField> and <NotArrayField>, this slot receives no slot props — there's no v-slot to bind here. <NotForm> only provides the form instance to descendants via context; to read form-level state like form.isSubmitting or form.isValid inside the slot, reference the form instance directly, as shown in the Usage example above.