DEV Community

Mustapha Abdul-Rasaq
Mustapha Abdul-Rasaq

Posted on • Updated on

Dynamically Add/Remove input fields using Vuejs

We all know how awesome Vuejs is as a frontend frame work and we are going to be exploring one of it's awesomeness by showing how to dynamically add or remove fields.
To ensure you get the best of this article, here are some assumptions.

  1. you know basic javascript such as writing a function().
  2. you know what a Vuejs Single File component is (trust me even a beginner understands this 😉 )

SFC.png
I am using TailwindCSS to handle styling so don't fret when you see some class names.

The Simple Logic.

  1. create a variable = phoneNumbers (an Array) that store all input fields
  2. a click handler to addField(inputField), this basically push into the array,
  3. a click handler to removeField(inputFieldIndex), this removes the index of the inputField from the array
  4. use a v-for directive to loop through the input fields to display them.

Let's get our hands dirty.

(1) Let's create a form with an input field

 <section class="w-full flex justify-center items-center my-10">
    <form class="">
      <div class="form-group">
        <label class="text-gray-600 font-semibold text-lg">Phone Number</label>
        <div class="input wrapper flex items-center">
          <input
            type="text"
            class="h-10 rounded-lg outline-none p-2"
            placeholder=" Enter Phone Number"
          />
          <!--          Add Svg Icon-->
          <svg
            xmlns="http://www.w3.org/2000/svg"
            viewBox="0 0 24 24"
            width="24"
            height="24"
            class="ml-2 cursor-pointer"
          >
            <path fill="none" d="M0 0h24v24H0z" />
            <path
              fill="green"
              d="M11 11V7h2v4h4v2h-4v4h-2v-4H7v-2h4zm1 11C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16z"
            />
          </svg>

          <!--          Remove Svg Icon-->
          <svg
            xmlns="http://www.w3.org/2000/svg"
            viewBox="0 0 24 24"
            width="24"
            height="24"
            class="ml-2 cursor-pointer"
          >
            <path fill="none" d="M0 0h24v24H0z" />
            <path
              fill="#EC4899"
              d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zm0-9.414l2.828-2.829 1.415 1.415L13.414 12l2.829 2.828-1.415 1.415L12 13.414l-2.828 2.829-1.415-1.415L10.586 12 7.757 9.172l1.415-1.415L12 10.586z"
            />
          </svg>
        </div>
      </div>
    </form>
  </section>
Enter fullscreen mode Exit fullscreen mode

htmlpage1.png

(2) In the data object, we add a key called phoneNumbers which is an array of object.

<script>
//Your Javascript lives within the Script Tag
export default {
  name: "AddRemove",
  data() {
    return {
      phoneNumbers: [{ phone: "" }],
    };
  },
};
</script>
Enter fullscreen mode Exit fullscreen mode

(3) using v-for directive, we can render the each input field in the phoneNumbers array and also bind a key to each rendered input field.

We can use the v-for directive to render a list of items based on an array. The v-for directive requires a special syntax in the form of item in items, where items is the source data array and item is an alias for the array element being iterated on:

   <label class="text-gray-600 font-semibold text-lg">Phone Number</label>
        <div
          v-for="(input, index) in phoneNumbers"
          :key="`phoneInput-${index}`"
          class="input wrapper flex items-center"
        >
          <input
            type="text"
            class="h-10 rounded-lg outline-none p-2"
            placeholder=" Enter Phone Number"
          />
          <!--          Add Svg Icon-->
          <svg
            xmlns="http://www.w3.org/2000/svg"
            viewBox="0 0 24 24"
            width="24"
            height="24"
            class="ml-2 cursor-pointer"
          >
            <path fill="none" d="M0 0h24v24H0z" />
            <path
              fill="green"
              d="M11 11V7h2v4h4v2h-4v4h-2v-4H7v-2h4zm1 11C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16z"
            />
          </svg>

          <!--          Remove Svg Icon-->
          <svg
            xmlns="http://www.w3.org/2000/svg"
            viewBox="0 0 24 24"
            width="24"
            height="24"
            class="ml-2 cursor-pointer"
          >
            <path fill="none" d="M0 0h24v24H0z" />
            <path
              fill="#EC4899"
              d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zm0-9.414l2.828-2.829 1.415 1.415L13.414 12l2.829 2.828-1.415 1.415L12 13.414l-2.828 2.829-1.415-1.415L10.586 12 7.757 9.172l1.415-1.415L12 10.586z"
            />
          </svg>
        </div>
Enter fullscreen mode Exit fullscreen mode

(4) using v-model directive, we can enable two way binding on form elements to get form element data. Don't forget phoneNumbers variable is an array of object, there for we can use the dot(.) notation to access object in the array.

    <input 
               v-model="input.phone"
               type="text" 
               class="h-10 rounded-lg outline-none p-2" 
               placeholder=" Enter Phone Number"     
          />
Enter fullscreen mode Exit fullscreen mode

(5) create the various Method Event Handlers (addField and removeField()). in the code below, we passed fieldType as a second args for addField(). fieldType is the input category eg phoneNumbers, emailAddresses, or any other (array) field you want to dynamically add or remove

<script>
export default {
  name: "AddRemove",
  data() {
    return {
      phoneNumbers: [{ phone: "" }],
    };
  },
  methods: {
    addField(value, fieldType) {
      fieldType.push({ value: "" });
    },
    removeField(index, fieldType) {
      fieldType.splice(index, 1);
    },
  },
};
</script>
Enter fullscreen mode Exit fullscreen mode

(6) Finally we bind the Handlers to our add and remove icons.
One last thing, let us conditionally render the delete button such that it only shows when the number of fields are greater than 1.
This can done using v-show directive where we can write a simple js expression

 <!--          Add Svg Icon-->
          <svg

            @click="addField(input, phoneNumbers)"
            xmlns="http://www.w3.org/2000/svg"
            viewBox="0 0 24 24"
            width="24"
            height="24"
            class="ml-2 cursor-pointer"
          >
            <path fill="none" d="M0 0h24v24H0z" />
            <path
              fill="green"
              d="M11 11V7h2v4h4v2h-4v4h-2v-4H7v-2h4zm1 11C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16z"
            />
          </svg>

          <!--          Remove Svg Icon-->
          <svg
            v-show="phoneNumbers.length > 1"
            @click="removeField(index, phoneNumbers)"
            xmlns="http://www.w3.org/2000/svg"
            viewBox="0 0 24 24"
            width="24"
            height="24"
            class="ml-2 cursor-pointer"
          >
            <path fill="none" d="M0 0h24v24H0z" />
            <path
              fill="#EC4899"
              d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zm0-9.414l2.828-2.829 1.415 1.415L13.414 12l2.829 2.828-1.415 1.415L12 13.414l-2.828 2.829-1.415-1.415L10.586 12 7.757 9.172l1.415-1.415L12 10.586z"
            />
          </svg>
Enter fullscreen mode Exit fullscreen mode

ar.gif
There you go, you should be able to dynamically add and remove fields using vuejs.

Gracias for reading this far, i know it was quite long but worth it.

Discussion (6)

Collapse
jvom profile image
José Miranda

Excellent article, just a correction in function removeField.

removeField(index, fieldType) {
      //type.splice(index, 1);
      fieldType.splice(index, 1);
}
Enter fullscreen mode Exit fullscreen mode
Collapse
geekmaros profile image
Mustapha Abdul-Rasaq Author

Gracias JosĂ© 👍

Collapse
nasrinafrozkakoli profile image
Nasrin Afroz Kakoli

It was so well instructed that I could learn in depth and knew what is happening there. Added a little modification to use the properties of actual object that was pushed with a dummy property before ; ex- {value : "" , }

addField(object, fieldType) {
    let newObject ={};
    for (const [key, value] of Object.entries(object)) {
        newObject[key]="";
    }
    fieldType.push(newObject);
},
Enter fullscreen mode Exit fullscreen mode
Collapse
furkanulutasx profile image
Furkan

Thanks. Github repo links?

Collapse
travs15 profile image
Alejandro Reyes

Thank you for sharing this, it was really useful!

Collapse
inkubus profile image
Kuba

Works great with @José Miranda corrections, thank you for sharing!