Form management can often become complex in modern applications. With Nuxt Form, you simplify the entire process, from submission to data validation and error handling, while remaining fully reactive thanks to Nuxt.
I recently published a Nuxt module, my very first public module, and I'm quite happy to be able to share it with the community. This composable adds functionalities similar to those found in Inertia/Vue, but using Nuxt.
For those unfamiliar with Inertia, it's a package I discovered at the same time as Laravel. Inertia helps simplify communication between the front-end and the back-end, particularly through its composables that facilitate form management.
One composable in particular inspired me to create this module: useForm(). It allows you to create forms with reactive data, error handling, data transformations, success messages, etc.
I therefore decided to transpose the developer experience (DX) offered by Inertia's useForm
to Nuxt. My goal is to make form management as smooth and intuitive as possible within the Nuxt ecosystem, while drawing inspiration from Inertia's best practices.
useForm
composable in NuxtThe main function available in Nuxt Form is useForm
. It allows you to create a reactive form and manage its state. Here's how you can use it:
const form = useForm({
email: '',
password: '',
})
This useForm
initializes the form fields (email
and password
in this example) with default values. It also generates a set of tools to interact with your form in a fluid and reactive way.
post
, put
, delete
One of the great strengths of Nuxt Form is the ability to easily send data using the post
, put
, patch
, and delete
methods. These methods allow you to make API calls while automatically managing the form's state. For example, to submit data:
form.post('/api/endpoint', {
onSuccess: (res) => {
console.log('Success:', res);
form.reset(); // Resets the form
},
onError: (err) => {
console.warn('Error:', err);
},
});
transform
The transform
method allows you to manipulate data before sending it. This is useful if you want to format or validate data (for example, remove extra spaces or normalize email formats).
form.transform((data) => {
return {
email: data.email.trim().toLowerCase(),
password: data.password.trim(),
}
}).post('/api/endpoint', {
onSuccess: (res) => {
console.log('Data submitted successfully', res);
},
onError: (err) => {
console.error('Error submitting data', err);
},
});
In this example, the form data is transformed before being sent, ensuring it is in the correct format.
form.errors
Nuxt Form provides simple and reactive error handling. The form.errors
composable allows you to easily manage and display errors specific to each form field.
<template>
<input v-model="form.email" type="text" placeholder="Enter your email" />
<p v-if="form.errors.email">{{ form.errors.email }}</p>
</template>
When errors occur (e.g., server-side validations), they are automatically assigned to form.errors
, and you can display them directly in your template.
With Nitro and Nuxt Form, managing form validation is simple and efficient. Here's how it works:
import { createUserValidator } from '../validators'
export default defineEventHandler(async (event) => {
const result = await readValidatedBody(event, createUserValidator.safeParse)
if (!result.success) {
return createValidationError(result.error)
}
// Save data to the database...
return { statusCode: 201, message: 'success' }
})
The approach involves reading the request body with readValidatedBody
. If validation fails, errors are returned via createValidationError
, which generates an HTTP response with status 422 - Unprocessable Entity. These errors are then dispatched to form.errors
, allowing you to easily display them in your user interface.
This method ensures robust server-side validation, essential for securing your forms in a Nuxt application. Furthermore, it integrates perfectly with reactive client-side error handling, providing a smooth user experience while maintaining optimal security.
reset
This all works perfectly when validation passes, but what about when errors occur? When an error is detected, it's crucial to be able to react quickly and reset the form or parts of it. This is where form.reset
comes in, a powerful tool to reset your form to its initial state, or simply to clear the problematic fields.
You can reset the entire form, or a specific field:
form.reset(); // Resets all fields
form.reset('password'); // Resets only the "password" field
onSuccess
and onError
in Nuxt FormWhen submitting a form, it's crucial to know whether the operation was successful or if errors occurred. With Nuxt Form, you can manage these events using callbacks like onSuccess
, onError
, and onFinish
, giving you complete control over the form submission flow.
onSuccess
: Manage Successful SubmissionsThe onSuccess
method is triggered when the form submission is successful. This allows you to perform additional actions, such as resetting the form or displaying a confirmation message to the user.
form.post('/api/endpoint', {
onSuccess: (response) => {
console.log('Successful submission:', response);
// Reset the form after a successful submission
form.reset();
}
});
In this example, after sending the data via POST
, onSuccess
is used to reset the form using form.reset()
, providing a smooth user experience.
This is particularly useful after a successful submission or if you want to allow the user to start over with blank values.
onError
: Manage Submission ErrorsWhen the submission fails, the onError
method comes into play. It catches the errors returned by the server, allowing you to display them to the user and take corrective actions, such as resetting only the erroneous fields in the form.
form.post('/api/endpoint', {
onError: (error) => {
console.error('Error during submission:', error);
form.reset("password")
}
});
With onError
, errors are handled in a targeted manner. In this example, if an error occurs during submission, only the password
field is reset using form.reset("password")
. This ensures that the other form fields remain unchanged, thus improving the user experience by limiting disruptions.
Voici la traduction en anglais avec un format Markdown :
Thanks to the onSuccess
, onError
, and onFinish
callbacks, you have full control over how submissions are handled in your Nuxt application. This allows you to customize user interactions based on the success or failure of the submission while maintaining smooth and reactive form management.
These submission management methods not only improve the user experience but also enhance the reliability and security of your server exchanges by ensuring clear handling of both errors and successes.
processing
The processing
field is a reactive property that indicates when an action is in progress, such as during form submission. This allows you to display a "loading" state or disable buttons while the request is being processed.
<button type="submit" :disabled="form.processing">Submit</button>
With this simple usage, you prevent multiple submissions while the form is being processed.
To install Nuxt Form and start managing your forms easily in a Nuxt application, simply use the Nuxt CLI. Run the following command in your terminal:
npx nuxi module add @louislschvn/nuxt-form
This command will automatically add the module to your Nuxt project, simplifying the management of reactive forms, validation, and submissions.
Yes, contributions are always welcome! If you want to improve Nuxt Form, you can clone the GitHub repository and start contributing. Here are the steps to set up the project locally:
git clone git@github.com:LouisLSCHVN/nuxt-form.git
npm run dev:prepare
npm run dev
Feel free to submit pull requests or report issues on the project's GitHub repository!
Thank you for taking the time to read this article. I hope you found answers to your questions and that this overview of the Nuxt Form module is helpful. Don’t hesitate to contribute to the project; all the instructions are available in the README.md file on the GitHub repository.
If you enjoyed the project, feel free to give it a star on GitHub to support me.