How to simply extend Vue.js text input custom component?

We have in our Vue.js based project the library of components. One of them is custom <v-text-input> component. That component extends (wraps) standard <input> component - you can type whatever you want and there are some additional features.

The only thing I like to change is to make our custom component “digits only”, that is to allow entering numbers (0-9) only, but that should be new component, for example <v-digits-input>. I think about using:

onkeypress="return event.charCode >= 48 && event.charCode <= 57"

But, I’m not sure how to implement it efficiently.

The code looks as following:

v-text-input.vue:

<template>
  <div class="v-text-input" :class="rootClasses">
    <div v-click-outside="unfocus" class="v-text-input-control" @click="focus">
      <div class="v-text-input-control-inner">
        <div v-if="iconPrepend" class="v-text-input__icon v-text-input__icon--prepend">
          ...
        </div>
        <div class="v-text-input-control-inner">
          <label>...</label>
          <input
            :id="id"
            ref="input"
            type="text"
            :readonly="readonly"
            :disabled="disabled"
            :placeholder="placeholder"
            v-bind="$attrs"
            :value="mutableValue"
            v-on="listeners"
          />
        </div>
        <slot name="icon">
          <div v-if="iconAppend" class="v-text-input__icon v-text-input__icon--append">
            ...
          </div>
        </slot>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { Vue, Component, Prop, Watch, Model } from 'vue-property-decorator';

@Component({ inheritAttrs: false })
export default class TextInputComponent extends Vue {
  ...
}

v-digits-input.vue:

<template>
  <v-text-input
    v-bind="$attrs"
    v-on="$listeners"
    onkeypress="return event.charCode >= 48 && event.charCode <= 57"
  />
</template>

<script lang="ts">
import { Vue, Component } from 'vue-property-decorator';

@Component({ inheritAttrs: false })
export default class TextInputComponent extends Vue {}
</script>

I’m not sure if this is correct approach.

Yes, perfectly normal. That said, why not use type="number" or apply a pattern?

Thank you for your feedback.

If you use type=“number”, you can type “e”, which is not allowed in my case.

Hey @tesicg
You can replace your onkeypress condition and call methods

@keypress="return event.charCode >= 48 && event.charCode <= 57"

replace in the template and define methods in the script tag.

@keypress="isNumber($event)"
methods: {
    isNumber: function (evt) {
      evt = evt ? evt : window.event;
      var charCode = evt.which ? evt.which : evt.keyCode;
      if (
        charCode > 31 &&
        (charCode < 48 || charCode > 57) &&
        charCode !== 46
      ) {
        evt.preventDefault();
      } else {
        return true;
      }
    },
  },

I hope this helps!!

Thank you.

1 Like