How to easily reuse forms in Vue

Web applications contain many forms today. Many times, we have the same form layout when creating or editing something (can be anything: user, project, to-do item, product, etc.). Usually, creating and editing a resource is implemented on 2 separate pages; but, being similar processes, we can always easily reuse it.

Fortunately, if you use Vue, you can easily implement reusable form components. Let's start then.

Let's create a reusable form component

We will create a simple form to create or edit a user. Without further ado, this is what the reusable form will look like in the end.

To simplify the process, the form will only have two fields, but you can use the same logic if you have more fields.

We are going to know first the components of creating and editing separately, then, we will see the combination of both.

Component to create elements

Easy to follow structure, a form, which we capture the submit event with @submit.prevent, our form fields with the v-model and the submit function to save data.

<template>
 <form @submit.prevent="submit">
   <input type="text" v-model="form.title" />
   <textarea v-model="form.description"></textarea>
   <button type="submit">Enviar</button>
 </form>
</template>
<script>
export default {
 mounted() {},
 data() {
   return {
     form: {
       title: "", //this.$root.animes[this.position].title,
       description: "",
     },
   };
 },
 methods: {
   submit: function () {
         //GUARDAR
     });
   },
 },
};
</script>

Component to Edit

For the initialization, it is exactly the same, except that we initialize the data, for that the mounted, and in the process of saving which you can update some list, send requests etc:

<template>
<form @submit.prevent="submit">
   <input type="text" v-model="form.title">
   <textarea v-model="form.description"></textarea>
   <button type="submit">Enviar</button>
</form>
</template>
<script>
export default {
   mounted() {

       this.position = this.$route.params.position
       this.form.title = this.$root.animes[this.position].title
       this.form.description = this.$root.animes[this.position].description
   },
 data() {
   return {
     position: 0,
     form: {
       title:"", 
       description: "",
     },
   };
 },
 methods: {
   submit: function () {
       // EDITAR
   },
 },
};
</script>

Component to Edit and Create

Now we are going to merge the previous components; for that, we have to receive some parameter from the parent component to know if we are editing or creating; in this case, we assume that it is a process that we can carry out through Vue Router:

this.position = this.$route.params.position || -1;

Already with this initialization, we determine if we initialize the data or not, as well as if we create or edit it when we send the form:

<template>
 <form @submit.prevent="submit">
   <input type="text" v-model="form.title" />
   <textarea v-model="form.description"></textarea>
   <button type="submit">Enviar</button>
 </form>
</template>
<script>
export default {
 mounted() {
   this.position = this.$route.params.position || -1;
   this.form.title =
     this.position !== -1 ? this.$root.animes[this.position].title : "";
   this.form.description =
     this.position !== -1 ? this.$root.animes[this.position].description : "";
 },
 data() {
   return {
     position: 0,
     form: {
       title: "", //this.$root.animes[this.position].title,
       description: "",
     },
   };
 },
 methods: {
   submit: function () {
     if (this.position !== -1)
// EDITAR
       this.$root.animes[this.position].title = this.form.title;
     else {
// CREAR
       this.$root.animes.push({
         id: this.$root.animes.length,
         title: this.form.title,
         description: this.form.description,
       });
     }
   },
 },
};
</script>

You can watch the following videos in which we see various aspects of forms in Vue:

- Andrés Cruz

En español
Andrés Cruz

Develop with Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz In Udemy

I agree to receive announcements of interest about this Blog.