5

I want to have an input mask on a specific input where it parses the user input into a human readable US phone number.

For example

User enter: 1231231234 User sees: (123)-123-1234

What I have done so far is, i made a watch method like the follow

switch (this.form.values.primary_phone.length) {
        case 3:
          return this.form.values.primary_phone = this.form.values.primary_phone.replace(/^([0-9]{3})$/, '($1)');
        case 6:
          return this.form.values.primary_phone = this.form.values.primary_phone.replace(/^([0-9]{3})([0-9]{3})$/, '($1)-$2');
        case 10:
          return this.form.values.primary_phone = this.form.values.primary_phone.replace(/^([0-9]{3})([0-9]{3})([0-9]{4})$/, '($1)-$2-$3');
      }

Now this updates the value only when I focus out of from input. Is there a way I can do it to update while the input is still at focus?

3 Answers 3

4

I would recommend you to do a directive wrapping the jquery plugin input mask.

There is an example:

JavaScript

Vue.directive('input-mask', {
  params: ['mask'],

  bind: function() {
    $(this.el).inputmask({
      mask: this.params.mask
    });

  },
});

var vm = new Vue({
  el: 'body',
  data: {
    value: '',
  }
});

HTML

<!-- Import Styles/Scripts from the plugin and do not forget the jQuery library -->
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/jasny-bootstrap/3.1.3/css/jasny-bootstrap.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/jasny-bootstrap/3.1.3/js/jasny-bootstrap.min.js"></script>

<p>Selected: {{value}}</p>
<input v-model="value" v-input-mask mask="(999) 999-9999">

If you need there is a JSBin to show you how it works.

Sign up to request clarification or add additional context in comments.

1 Comment

I would not recommend using jQuery to solve this, rather I would use Vue's built-in filter method, or a combination of v-bind:value and v-on:keyDown, similar to what's shown here: vuejs.org/v2/guide/…
3

For that you must define a custom filter on your input. Something like this

Vue.filter('mask', function (value) {
  if (value.length <= 3){
    var re = new RegExp("^([0-9]{"+value.length+"})$");
    return value = value.replace(re, '($1)');
  } 
  if (value.length > 3 && value.length <= 6){
    var re = new RegExp("^([0-9]{3})([0-9]{"+ (value.length - 3)+"})$");
    return value = value.replace(re, '($1)-$2');
  }
  if (value.length > 6 && value.length <= 10){
    var re = new RegExp("^([0-9]{3})([0-9]{3})([0-9]{"+(value.length-6)+"})$");
    return value = value.replace(re, '($1)-$2-$3');
  }
    return value;
})

Then apply that to your template. I made a jsfiddle (based on the markdown example from Vue page)

Notice that you still have to handle values of length greater than 10, and I also changed your function to use if statements instead of switch-case

Comments

0

I use the text-mask plugin which give the same great functionality as the JQuery one without the Jquery bloat.

Github here: https://github.com/text-mask/text-mask

Vue instructions here: https://github.com/text-mask/text-mask/tree/master/vue

const MaskedInput = window.vueTextMask.default
new Vue({
    el: '#app',
    components: { MaskedInput },
    data: {
        phone: '',
        mask: ['(', /\d/, /\d/,/\d/, ')', '-', /\d/, /\d/, /\d/, '-', /\d/, /\d/, /\d/, /\d/]
    }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vueTextMask.min.js"></script>
<div id="app">
    phone:
    <masked-input v-model="phone" :mask="mask" placeholder="(___)-___-____"></masked-input>
</div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.