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.
- you know basic javascript such as writing a
function()
. - you know what a Vuejs Single File component is (trust me even a beginner understands this 😉 )
I am using TailwindCSS to handle styling so don't fret when you see some class names.
The Simple Logic.
- create a variable = phoneNumbers (an Array) that store all input fields
- a click handler to addField(inputField), this basically push into the array,
- a click handler to removeField(inputFieldIndex), this removes the index of the inputField from the array
- 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>
(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>
(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>
(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"
/>
(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>
(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>
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.
Top comments (7)
Excellent article, just a correction in function removeField.
Gracias José 👍
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 : "" , }
Thanks. Github repo links?
thx man
Works great with @José Miranda corrections, thank you for sharing!
Thank you for sharing this, it was really useful!