The following is a partnership between Packt Publishing and me. The idea is for me to be a channel of valuable information made by independent publishers.

This disclaimer informs readers that the views, thoughts, and opinions expressed in the text belong solely to the author.

How to use V-Masks when building forms with Vue

One of the key aspects of any successful form is clarity. If the user finds the form easy to use and easy to understand, they are more likely to fill it in, and submit it. In this chapter, we are going to be looking at input masking. You will learn how to quickly and easily apply masks to your form inputs, and to configure them to your needs with real-life examples, such as telephone numbers.

This is an extract taken from Building Forms with Vue.js written by Marina Mosti (@MarinaMosti). Marina is speaking at VueConf in Toronto in November. Learn more here.

What exactly are input masks? They are predefined structures that display the data for an input. For example, if you were going to mask a telephone input, you’d probably want it to display as (123) 234-5555, instead of simply, 1232345555. You can clearly see that the first example is not only easier to read, but it also conveys meaning about what the field is trying to accomplish. Input masks are a nice feature to take your UX to another level, and they are very easy to implement, thanks to open source libraries such as v-mask. The GitHub repository page can be found here.

How to install the v-mask library

Let’s get started with the installation of the v-mask library. In order for our project to use what it has to offer, we first need to add it to our project dependencies. Follow these steps in order to do this:

1) Open up your Terminal, and type in the following command to add the library to our dependencies:

  npm install v-mask

2) We need to add it to Vue as a plugin, so head to main.js, and let’s both import it, and let Vue know that we want to register it as a plugin for all of our apps. Add the following code, after the import App line:

import VueMask from 'v-mask' Vue.use(VueMask);

Now that we have registered our plugin, we have access to a new directive: v-mask. We can add this new directive directly onto our <input> elements, and the library will handle the masking behind the scenes by reading the users’ input, and adjusting the display of the field. Let’s try this on a regular input first, then we will add some props to our project’s component.

3) Go to App.vue, and create a new <input> element after the email input:

<input type="text" />

If we were to type in a phone number in this field as it is, we would get the default input behavior. Anything goes. So, let’s apply a telephone number mask to it. Our new v-mask library has a requirement that every field that we apply it to needs to be v-modeled, so let’s get that done first.

4) Add a new telephone prop to our data() inside of the form object:

form: {
  // ...
  telephone: ''

5) Now, go back to our new <input> element, and apply v-model. We are also going to now add the v-mask directive, shown as follows:

<input type="text" v-model="form.telephone" v-mask="'(###)###-####'">

Go back to your browser, and try the input once again. As you type, you will see that you are actually getting it nicely formatted to what we would expect for a telephone number. In five simple steps, we have added input masking to one of our form fields. Now let’s take a look in more depth at what the v-mask directive does.

What is a directive?

When we added the v-mask library to our project, and added the plugin within main.js, the library created a new directive for us, v-mask.

What exactly is a directive, though? We know it looks like an HTML attribute, but what else?

Directives are special attributes with the v- prefix. Directive attribute values are expected to be a single JavaScript expression (with the exception of v-for […]). A directive’s job is to reactively apply side effects to the DOM, when the value of its expression changes.

Okay, so it looks like we have a special attribute that can modify the element. That sounds exactly like what we saw happen, when we applied to the input element. But, how does the actual expression or value that we are putting into this directive work?

We know from the example that we are passing in a string, and you can see that inside the double quotes that make up the v-mask="" attribute, we are setting a new pair of single quotes ('). This means that the expression inside this attribute is JavaScript, and that we are passing it a string value.

From looking at the v-mask library documentation, we know that we have a few special placeholder characters that we can use inside our masks. The table for those is as follows:

Symbol Meaning
# Number (0-9)
A Letter in any case (a-z, A-Z)
N Number or letter
X Any Symbol
? Optional (next character)

Take for example, a mask that will display the time of the day. You could define it as follows:


This means that this input will take two numbers from 0 to 9 (##), followed by a : character, followed by another two numbers (##).

Anything that does not match this pattern, will be ignored by the input. v-mask is a very powerful library that allows us to customize exactly how we want our input to be displayed, by combining these simple rules. In the final section of this post, we’ll look at how to modify custom inputs. This will allow us to fully leverage the power of the input masks.

How to enhance custom inputs

We have put in a lot of work to create our awesome custom BaseInput, so we definitely want to keep using it! Follow these steps in order to modify the BaseInput, and to allow for input masking:

1) Go back to App.vue, and switch the <input> element for a <BaseInput> component:

<BaseInput label="Telephone" type="text" v-model="form.telephone" />

Let’s go into BaseInput.vue now, and create a new prop; we will call it mask, and it will default to an empty string. It is important that we default it to an empty string, or else the directive will try to match, and we won’t be able to type into the fields if they don’t have a declared mask!

2) Add it to your props object:

// ...,
mask: {
  type: String, required: false

3) Now, go back to App.vue, and update our telephone BaseInput to use the mask attribute:

<BaseInput label="Telephone" type="text"

All done! Return to your browser, and add some numbers to the field, and you should have a nice-looking telephone mask working with your custom component!

Blog Logo

Tomas Alabes

Software Engineer, author, blogger and obsessive learner, from Argentina living in Silicon Valley



Tomas Alabes' Blog

My personal site's blog

Back to Overview