Skip to content

Add a useForm composable to Nuxt, and a createValidationError function to validate forms in Nitro

Notifications You must be signed in to change notification settings

lschvn/nuxt-form

Repository files navigation

Nuxt Form

npm version npm downloads License Nuxt

My new Nuxt module for doing amazing things.

Features

  • ⛰  Form handling similar to Inertia/Vue's useForm
  • 🚠  Backend validation with Zod
  • 🌲  Frontend form state management
  • 🏔  Easy error handling and validation

Quick Setup

Install the module to your Nuxt application with one command:

npx nuxi module add @louislschvn/nuxt-form

That's it! You can now use Nuxt Form in your Nuxt app ✨

Documentation

Backend Usage

Nuxt Form provides a utility function createValidationError for easy backend validation:

import { createUserValidator } from '../validators'

export default defineEventHandler(async (event) => {
  const result = await readValidatedBody(event, createUserValidator.safeParse)
  if (!result.success) {
    return createValidationError(result.error)
  }
  // Store in database..
  return { statusCode: 201, message: 'success' }
})

Frontend Usage

On the frontend, you can use the useForm composable to handle form state and submission:

<template>
  <form @submit.prevent="submit">
    <input v-model="form.email" type="text" placeholder="Enter your email">
    <p v-if="form.errors.email">{{ form.errors.email }}</p>

    <input v-model="form.password" type="password" placeholder="Enter your password">
    <p v-if="form.errors.password">{{ form.errors.password }}</p>

    <button type="submit" :disabled="form.processing">Submit</button>
  </form>
  <p v-if="success.state">Success!</p>
</template>

<script setup>
const form = useForm({
  email: '',
  password: '',
})

const success = ref({ state: false, message: '' })

const submit = async () => {
  form.post('/api/endpoint', {
    onError: (err) => {
      form.reset('password')
      console.warn(err)
    },
    onSuccess: (res) => {
      success.value.state = true
      success.value.message = res.message
      form.reset()
    },
  })
}
</script>

This setup provides a seamless integration between frontend form handling and backend validation, similar to the functionality offered by Inertia.js and Vue's useForm, but tailored for Nuxt applications.

File Uploads

Nuxt Form also supports file uploads in a simple and efficient way. You can manage file uploads alongside your form data, and it even provides upload progress tracking.

Example of File Upload

In the example below, you can see how to add a file upload input to your form. The file selected will be sent with the rest of the form data when submitted.

<template>
  <form @submit.prevent="submit">
    <input
      type="file"
      @change="form.avatar = $event.target.files[0]"
    >
    <progress
      v-if="form.progress"
      :value="form.progress"
      max="100"
    >
      {{ form.progress.percentage }}%
    </progress>

    <button
      type="submit"
      :disabled="form.processing"
    >
      Submit
    </button>
  </form>
</template>

<script setup>
const form = useForm({
  avatar: null | File,
})

const submit = () => {
  form.post('/api/endpoint')
}
</script>

Key Features of File Handling:

  • Automatically manage file uploads with the form data.
  • Track upload progress with a visual progress bar.

Todo

  • Handle file uploads
  • Make success state natively available in the composable

Contribution

Local development
# Install dependencies
npm install

# Generate type stubs
npm run dev:prepare

# Develop with the playground
npm run dev

# Build the playground
npm run dev:build

# Run ESLint
npm run lint

# Run Vitest
npm run test
npm run test:watch

# Release new version
npm run release