javascriptvue.jsvuejs3primevue

How to disable changing the value of <InputNumber> component using up, down, etc. arrows?


Is there a way to disable the InputNumber component value from changing when pressing Up Arrow, Down Arrow, Home, End keys?

I tried this but it doesn't help:

const onKeyDown = e => {
    if (e.key === 'ArrowUp') {
        e.preventDefault();
        return false;
    }
};

example in sandbox


Solution

  • Although @KrysztofKrzeszewski pointed out the answer, unfortunately, it is not possible to influence the behavior externally, but we have the option to override it. However, this does not mean that we cannot use the original functionality (@KrysztofKrzeszewski created a duplication in the answer, which doesn't follow updates).

    Before overriding, create a backup of the original function, then call it after your own logic, like this:

    import { ref, onMounted } from 'vue';
    
    const value = ref(50);
    
    const myInputNumber = ref(null);
    onMounted(() => {
      const originalOnKeyDown = myInputNumber.value.onInputKeyDown;
      myInputNumber.value.onInputKeyDown = (e) => {
        if (['ArrowUp', 'ArrowDown', 'Home', 'End'].includes(e.key)) {
          e.preventDefault();
          return;
        }
    
        originalOnKeyDown(e);
      };
    });
    
    <InputNumber
      ref="myInputNumber"
      inputId="minmax"
      v-model="value"
      :min="0"
      :max="100"
    />
    

    Update

    My answer inspired @KrzysztofKrzeszewski, so now their answer is complete: Revision #3

    Use the bind() function to correctly define the this.

    My solution was complemented with a very correct this fix by @Krzysztof, which ensures that the original function will always run with its own this. I will also add the updated answer with some documentation and explanation.

    The bind() method of Function instances creates a new function that, when called, calls this function with its this keyword set to the provided value, and a given sequence of arguments preceding any provided when the new function is called.

    So the completed answer:

    import { ref, onMounted } from 'vue';
    
    const value = ref(50);
    
    const myInputNumber = ref(null);
    onMounted(() => {
      const originalOnKeyDown = myInputNumber.value.onInputKeyDown.bind(myInputNumber.value);
      myInputNumber.value.onInputKeyDown = (e) => {
        if (['ArrowUp', 'ArrowDown', 'Home', 'End'].includes(e.key)) {
          e.preventDefault();
          return;
        }
    
        originalOnKeyDown(e);
      };
    });
    
    <InputNumber
      ref="myInputNumber"
      inputId="minmax"
      v-model="value"
      :min="0"
      :max="100"
    />