Tony
Tony

Reputation: 1432

Prevent delete or backspace key from triggering @input event

I have two event listeners on an input component(@input and @keyup.delete). I am using the @input listener to detect keys and handle their usage accordingly, while I want to also detect when a user taps the delete or backspace button, so that I can change the index in a pin field.

BaseInputField.vue

<template>
  <div>
    ...
    <input
      ...
        :value="value"
        @keyup.delete="$emit('delete-or-backspace-key-pressed')"
        @input="$emit('input', $event.target.value)"
       ...
    />
     ...
  </div>
</template>

ParentContainer.vue

<BaseInputField
  ...
    @input="handleInput"
    @delete-or-backspace-key-pressed="handleDeletion"
  ...
/>

The problem is that pressing the del or backspace button also triggers the @input event, and it's messing with my implementation.

I would appreciate help on preventing this behaviour without the use of Keycodes, as according to Vue documentation, they are deprecated and may not work with newer browsers.

Upvotes: 4

Views: 19373

Answers (2)

sugars
sugars

Reputation: 1493

Just change the BaseInputField.vue to the following:

<template>
  <input
    :value="value"
    @keyup.delete="triggerDBKey"
    @input="triggerInput"
    @paste="triggerPaste"
  />
</template>

<script>
export default {
  name: 'BaseInputField',
  props: {
    value: {type: String, default: ''}
  },
  data() {
    return {
      originalValue: this.value
    }
  },
  methods: {
    triggerInput(e) {
      if (this.originalValue.length > 0 && this.originalValue.length > e.target.value.length) return
      this.originalValue = e.target.value
      this.$emit('input', e.target.value)
    },
    triggerDBKey(e) {
      if (e.target.value === '') {
        this.originalValue = ''
      }
      this.$emit('delete-or-backspace-key-pressed')
    },
    triggerPaste(e) {
      this.$emit('paste')
    }
  }
}
</script>

Prevent the input event from being triggered by judging the content length before and after editing.

Here is my codesandbox

Upvotes: 2

Owl
Owl

Reputation: 6853

You can use event.key instead, but you need to use @keydown event instead of @input

event.key value will be "Backspace" or "Delete" if you press backspace / del respectively.

And you can do preventDefault on your handleInput function to prevent the input value deletion. So instead of passing $event.target.value, pass the whole $event object from the input

@keydown="$emit('input', $event)"

and on your handleInput function:

handleInput(e) {
      if (e.key === "Backspace" || e.key === "Delete") {
          return e.preventDefault(); // Don't do anything to the input value
      }
      const value = e.target.value;
      // do something with value
}

Demo: https://codesandbox.io/s/fast-snowflake-xpwqm?file=/src/App.vue

Upvotes: 6

Related Questions