Search code examples
javascriptvue.jsmasking

Vue component get and set conversion with imask.js


I am trying to use iMask.js to change 'yyyy-mm-dd' to 'dd/mm/yyyy' with my component however when I am setting the value I think it is taking the value before the iMask has finished. I think using maskee.updateValue() would work but don't know how to access maskee from my component.

I am also not sure if I should be using a directive to do this.

Vue.component("inputx", {
  template: `
  <div>
  <input v-mask="" v-model="comp_date"></input>
  </div>
    `,
  props: {
    value: { type: String }
  },
  computed: {
    comp_date: {
      get: function () {
        return this.value.split("-").reverse().join("/");
      },
      set: function (val) {
        const iso = val.split("/").reverse().join("-");            
        this.$emit("input", iso);
      }
    }
  },
  directives: {
    mask: {
      bind(el, binding) {
        var maskee = IMask(el, {
          mask: "00/00/0000",
          overwrite: true,
        });
      }
    }
  }
});

var app = new Vue({
  el: "#app",
  data: {
    date: "2020-12-30"
  }
});
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>
<script src="https://unpkg.com/imask"></script>

<div id="app">
    <inputx v-model="date"></inputx>    
    Date: {{date}}
</div>


Solution

  • The easiest way you can achieve this is by installing the external functionality on the mounted hook of your Vue component, instead of using a directive.

    In this way you can store the 'maskee' object on your component's data object to later access it from the setter method.

    Inside the setter method you can then call the 'updateValue' method as you hinted. Then, you can extract the processed value just by accessing the '_value' prop of the 'maskee' object.

    Here is a working example:

     Vue.component("inputx", {
    template: `
    <div>
    <input ref="input" v-model="comp_date"></input>
    </div>
      `,
    data: {
      maskee: false,
    },
    props: {
      value: { type: String },
    },
    computed: {
      comp_date: {
        get: function () {
          return this.value.split("-").reverse().join("/");
        },
        set: function () {
          this.maskee.updateValue()
          const iso = this.maskee._value.split("/").reverse().join("-");            
          this.$emit("input", iso);
        }
      }
    },
    mounted(){
      console.log('mounted');
      const el = this.$refs.input;
    
      this.maskee = IMask(el, {
        mask: "00/00/0000",
        overwrite: true,
      });
      console.log('maskee created');
    }
      });
    
    var app = new Vue({
      el: "#app",
      data: {
        date: "2020-12-30"
      }
    });
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>
    <script src="https://unpkg.com/imask"></script>
    
    <div id="app">
        <inputx v-model="date"></inputx>    
        Date: {{date}}
    </div>