1

I have worked with VueJS for a while, and it is great. I have been able to integrate it with jQueryUI (for an old looking website) and I created a datepicker component, and a datetime picker component as well, both working correctly.

Now I am trying to create a simple phone number component, which simply provides an input with a mask that helps with the phone number format. The plugin for jquery that provides the masking, works correctly on it's own, but if I try to mask an input inside my component, it does not work.

Here is the example code in jsfiddle:

Simple Masked Phone input component for vuejs 2.4.0 - jsfiddle

Javascript:

Vue.component('phone', {
  template: '#phone',
  props: {
    value : {
      type   : String,
      default: ''
    },
    mask: {
      type   : String,
      default: '(999) 999-9999'
    }
  },
  data: function() {
    return {
        internalValue: ''
    };
  },

    created: function() {
    this.internalValue = $.trim(this.value);
  },

  mounted: function() {
    $(this.$el).find('.phone:eq(0)').mask('(999) 999-9999');
  },

  methods: {
    updateValue: function (value) {
            this.$emit('input', value);
    }
  }
});

var vueapp = new Vue({
  el: '#content',
  data: {
    myphone: ''
  }
});

$('.phonex').mask('(999) 999-9999');

HTML:

<div id="content">
  <script type="text/x-template" id="phone">
    <input type="text" class="phone" v-model="internalValue" v-on:input="updateValue($event.target.value)" />
  </script>

  <label>Vue Phone</label>
  <phone v-model="myphone"></phone>
  <br />
  {{ myphone }}
  <br />

  <label>Simple Phone</label>
  <input type="text" class="phonex" />
</div>

This is what I see:

jsfiddle result

Dependencies:

Is there anything I am doing wrong here? Thanks.

1 Answer 1

2

You don't need the .find('.phone:eq(0)') in your jquery, removing it seems to fix the masking (as shown here), though this does seem to mess with Vue's data binding.

After doing a bit more digging it looks like this is a known issue.

And is addressed here:

Vue is a jealous library in the sense that you must let it completely own the patch of DOM that you give it (defined by what you pass to el). If jQuery makes a change to an element that Vue is managing, say, adds a class to something, Vue won’t be aware of the change and is going to go right ahead and overwrite it in the next update cycle.

The way to fix this is to add the event handler when you call .mask on the element.

So for example:

mounted: function() {
  var self = this;
    $(this.$el).mask('(999) 999-9999').on('keydown change',function(){
        self.$emit('input', $(this).val());
    })
  },

Here is the fiddle with the fix: https://jsfiddle.net/vo9orLx2/

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

1 Comment

Thank you so much for your answer. As seen in the provided example, it works. Here is an example (based on the accepted answer) where the component has more elements inside, just as a reference if anyone else need it: jsfiddle.net/jdavidzapatab/Lk0twvn2

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.