Creating a Vue 3 Form Repeater Component: A Step-by-Step Guide
Tags: vue, beginners, tutorial, webdev
Published: 2023-08-07 13:46:05

## Introduction

Vue.js is a popular JavaScript framework for building user interfaces and interactive web applications.

In this article, we will walk you through the process of creating a Vue 3 Form Repeater component, which allows users to dynamically add and remove form fields. 

This powerful component is handy when dealing with forms that require variable numbers of inputs, such as dynamic surveys or questionnaires.

## Personal experience

As I was developing a **travel reservations application**, I encountered a significant challenge when it came to allowing users to plan multi-destination trips. 

The goal was to provide users with a **seamless experience** in adding multiple destinations to their itineraries. Traditionally, this would involve creating a fixed number of input fields for each destination, which wouldn't be practical for trips with varying numbers of stops. 

To address this issue, I decided to implement a **Form Repeater** component, which would enable users to dynamically add or remove destinations as needed. 

This component allowed me to provide a user-friendly interface where travelers could effortlessly customize their trips. 

With the form repeater, users could add new destinations by simply clicking the "Add Destination" button and remove them just as easily with the "Remove Destination" button. 

As they added or removed destinations, the form would dynamically update to reflect the changes, making the entire trip planning process smooth and intuitive.

In this article, I will guide you to a simple but effective approach on how to build one.

Let's get started!

### 1. Set Up Your Vue 3 Project

Before we begin, make sure you have Vue 3 installed. 
If not, you can install it using Vue CLI by running the following commands in your terminal:

```bash
npm install -g @vue/cli
vue create vue-form-repeater
cd vue-form-repeater
```


### 2. Create the Form Repeater Component

Inside the "src" folder of your project, create a new file called "FormRepeater.vue". 
This file will contain the definition of our custom Form Repeater component.


### 3. Define the Form Repeater Component

In the "FormRepeater.vue" file, define the component's template and script. 
For the sake of simplicity, we will create a form repeater with text input fields. 
However, you can customize it to include different types of form elements like checkboxes, radio buttons, or select dropdowns.

```html
<template>
  <div>
    <div v-for="(field, index) in fields" :key="index">
      <input v-model="field.value" type="text" :placeholder="`Field ${index + 1}`">
    </div>
    <button @click="addField">Add Field</button>
    <button @click="removeField">Remove Field</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      fields: [{ value: '' }], // Initialize with an empty field
    };
  },
  methods: {
    addField() {
      this.fields.push({ value: '' });
    },
    removeField() {
      if (this.fields.length > 1) {
        this.fields.pop();
      }
    },
  },
};
</script>
```

### 4. Using the Form Repeater Component

In your main app file (e.g., App.vue), you can now import and use the Form Repeater component as follows:

```html
<template>
  <div>
    <h1>Form Repeater Example</h1>
    <FormRepeater />
  </div>
</template>

<script>
import FormRepeater from './FormRepeater.vue';

export default {
  components: {
    FormRepeater,
  },
};
</script>
```

### 5. Add a Submit Button

In the "FormRepeater.vue" template, we'll add a submit button at the end of the form:

```html
<template>
  <div>
    <div v-for="(field, index) in fields" :key="index">
      <input v-model="field.value" type="text" :placeholder="`Field ${index + 1}`">
    </div>
    <button @click="addField">Add Field</button>
    <button @click="removeField">Remove Field</button>
    <button @click="onSubmit">Submit</button>
  </div>
</template>
```

### 6. Implement the onSubmit Function

In the "FormRepeater.vue" script, let's add the `onSubmit` method that will handle the form submission:

```html
<script>
export default {
  data() {
    return {
      fields: [{ value: '' }], // Initialize with an empty field
    };
  },
  methods: {
    // ... existing methods ...

    onSubmit() {
      // Create an object to hold the form data and add all the field values to it.
      const formData = {};
      this.fields.forEach((field, index) => {
        formData[`Field ${index + 1}`] = field.value;
      });

      // Your submit logic here (e.g., sending the formData to the server or handling it as needed)
      // For demonstration purposes, we'll log the form data to the console.
      console.log('Form data:', formData);
    },
  },
};
</script>
```

### 7. Using the Form Repeater Component with onSubmit


Now that we've added the `onSubmit` function, you can use it in your main app file (e.g., App.vue) when defining the Form Repeater component:

```html
<template>
  <div>
    <h1>Form Repeater Example</h1>
    <FormRepeater @submit="handleFormSubmit" />
  </div>
</template>

<script>
import FormRepeater from './FormRepeater.vue';

export default {
  components: {
    FormRepeater,
  },
  methods: {
    handleFormSubmit(formData) {
      // Handle the form submission here, e.g., send the formData to the server.
      console.log('Form data submitted:', formData);
    },
  },
};
</script>
```

### 8. Run Your App

With everything set up, you can now start your Vue app and see the Form Repeater in action:

```bash
npm run serve
```

## Conclusion
Congratulations! 

You've successfully built a Vue 3 Form Repeater component, allowing users to add and remove form fields dynamically. 

This component is a valuable addition to any project that involves creating dynamic forms with varying input requirements. 

Feel free to customize the form fields and add styles to match your project's design.

**References**
- Official Vue.js documentation: [https://v3.vuejs.org/](https://v3.vuejs.org/)
- Vue CLI documentation: [https://cli.vuejs.org/](https://cli.vuejs.org/)