Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue JS - How to restrict special characters in an input field?

What's the best way to implement text-character restrictions in Vue JS ? I am looking to achieve with RegExp so that the user will not be allowed to type the symbols in the field.

like image 487
vinoth Avatar asked May 28 '18 12:05

vinoth


2 Answers

I use a two pronged approach:

First is to use a watch or computed value with a setter, as Daniel recommends above. Besides handling keyboard input, it also handles input via drag and drop, paste, or whatever else the user comes up with.

Second is a keydown handler. When using only a watched value, there is a slight delay in the UI. The restricted character is briefly displayed before being removed. For a more seamless user experience, the keydown listener cancels the keyboard event for invalid input.

new Vue({
  el: "#app",
  data: {
    name: "",
  },
  watch: {
    name(val) {
      this.name = val.replace(/\W/g, "");
    },
  },
  methods: {
    nameKeydown(e) {
      if (/^\W$/.test(e.key)) {
        e.preventDefault();
      }
    },
  },
});
html {
  font-family: sans-serif;
}

.demo {
  display: flex;
  justify-content: space-between;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<main id="app">
  <p>Try typing spaces, punctuation, or special characters into each box to see the difference made by the key handler.</p>
  <div class="demo">
    <div>
      <div>Without key handler:</div>
      <input type="text" v-model="name" />
    </div>
    <div>
      <div>With key handler:</div>
      <input type="text" v-model="name" @keydown="nameKeydown($event)" />
    </div>
  </div>
</main>
like image 196
gilly3 Avatar answered Oct 02 '22 13:10

gilly3


Either using a watch or a computed value with setter and getter.

watch: {
  myAlphaNumField(newVal) {
    let re = /[^A-Z0-9]/gi;
    this.$set(this, 'myAlphaNumField', newVal.replace(re, ''));
  }
}

If you want the regex to match a pattern exactly, the trick is in defining the regular expression in such a way that it allows all the characters up to the last.

For example, if you want to have exactly 5 digits (#####), the regex should be \d{1,5} and not \d{5}, because you need to be able to type the first four before that, though you would still use that later one to verify if the field is finished/complete/valid.

another example, for A#A#A# would be [A-Z]([0-9]([A-Z]([0-9]([A-Z]([0-9])?)?)?)?)? The point is, that each character after the first is optional, but only if the preceding character is available

one more example for ###-AA : \d(\d(\d(\-(\w(\w)?)?)?)?)?

you can also use an existing library such as https://github.com/insin/inputmask-core (which does not include the vue extension), or https://github.com/niksmr/vue-masked-input (which does)

like image 24
Daniel Avatar answered Oct 02 '22 13:10

Daniel