The bad practice to avoid in your VueJS forms

NicolasBrondinBernard

Author
@NicolasBrondinBernard

If you're making this mistake, it's not too late to start using `<form>` elements again!

Article published on 03/04/2023, last updated on 10/08/2026

I'd stake my life on it: 95% of the forms you build with VueJS look like this:

<div class="form">
    <label for="email">Email *</label>
    <input type="email" id="email" v-model="email" />
    <label for="password">Password *</label>
    <input type="password" id="password" v-model="password" />
    <p v-if="error">{{ error }}</p>
    <button @click="send()">Envoyer</button>
</div>

Of course, maybe you use a library to generate and style your <input>, so your form is slightly different, but a real design flaw is hiding behind this form...

This flaw is that it's not actually a form!

Why use a
element?

With modern front-end frameworks and the use of asynchronous HTTP requests (ajax), the element has come to seem completely useless to many, since it only served to send information to the server synchronously.

But that's wrong!

In reality, many native web features are made possible through the use of HTML forms, which greatly improves user experience, accessibility, and also the developer experience!

For example, by using a element, you can:

  • Use the native "required" attribute to indicate that a field is required, thus blocking form submission without adding any JavaScript
  • Use the "pattern" attribute to validate the field with a RegEx (as well as "minlength" and "maxlength")
  • Automatically submit the form when the "Enter" key is pressed
  • Semantically indicate to the browser that all fields belong to the same form, making things easier for accessibility assistance tools

There are surely other benefits, so if you know of any, feel free to send them our way!

Best practice

The best practice is therefore to use a and listen to the native "submit" event:

<form @submit="send()">
    <label for="email">Email *</label>
    <input 
           type="email" 
           pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$" 
           id="email" 
           v-model="email" 
    />
    <label for="password">Password *</label>
    <input 
           type="password" 
           minlength="8" 
           id="password" 
           v-model="password" 
    />
    <button type="submit">Envoyer</button>
</div>

<script>
export default {
    setup(){
        function send(ev){
            //Empèche le formulaire de recharger la page
            ev.preventDefault();
            // Le code de votre requête vient ici
            //...
        }
    }
}
</script>

So how does this work?

If you're not used to working with forms, some things in the code above might seem strange, so here are a few explanations:

First, a without an [action="..."] attribute will reload the current page upon submission, so you need to call the ev.preventDefault() method when the form is submitted to prevent the page from reloading.

Finally, you should know that the form will be submitted automatically if a


CHUTTERSNAP sur Unsplash

Finished reading this article?
Our complete courses
Take it to the next level with our courses!

Complete courses, exercises and certificates to really learn programming!

4.8 average rating

Comments (0)

to leave a comment

No comments yet