6

I'm going to build a customized virtual keyboard, so that's the first problem I've encountered. I have an input element, whose value is changed from outside, in my case by pressing a button. The problem is that there seems to be no way to trigger the normal 'change' event.

Neither clicking outside the input, nor pressing Enter gives any result.

What might be the correct way of solving this problem?

<template>
  <div class="app-input">
    <input @change="onChange" type="text" v-model="value" ref="input">
    <button @click="onClick">A</button>
  </div>
</template>

<script>
export default {
  name: "AppInput",
  data() {
    return {
      inputDiv: null,
      value: ""
    };
  },
  props: {
    msg: String
  },
  methods: {
    onClick() {
      this.value = this.value + "A";
      this.inputDiv.focus();
    },
    onChange() {
      alert("changed");
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.inputDiv = this.$refs.input;
    });
  }
};
</script>

The whole pen can be found here.

0

2 Answers 2

6

v-on:change would only trigger on a direct change on the input element from a user action.

What you are looking for is a watcher for your data property, whenever your value changes, watcher will execute your desired function or task.

watch: {
  value: function() {
    this.onChange();
  }
}

The watch syntax is elaborated on the provided official vuejs docs link. Use your data property as the key and provide a function as a value.

Check the snippet:

export default {
  name: "AppInput",
  data() {
    return {
      inputDiv: null,
      value: ""
    };
  },
  props: {
    msg: String
  },
  methods: {
    onClick() {
      this.value = this.value + "A";
      this.inputDiv.focus();
    },
    onChange() {
      alert("changed");
    }
  },
  // this one:
  watch: {
    value: function() {
      this.onChange();
    }
  },
  // --- rest of your code;
  mounted() {
    this.$nextTick(() => {
      this.inputDiv = this.$refs.input;
    });
  }
};
Sign up to request clarification or add additional context in comments.

11 Comments

The problem is that if it triggers onChange on every value change (which will be with the watcher) this is not how the vanilla input works.
the event you are talking about is the change event, it usually works like when you type something and the input element loses focus, and if there is any change the event triggers, but when you are choosing to click on the custom button, your input element already lost focus, I am not sure how else you can capture the change, or how do you know user has done changing since they are not providing inputs from the keyboard, and your input element lost focus, and you are manually focusing it each time
I understand this, that's why I'm wondering, what could be the solution...
@EugeneBarsky Then you should realize why these 2 statements cannot coexist: "The problem is that if it triggers onChange on every value change" - "I'd like it to work as close as possible to an ordinary input, where we have the change event on focus blur, enter etc. Not on addition of a letter". It can't be both ways.
It's not clear what you want. You can either do some processing after every letter change or choose another event to process from, like Enter keypress. It's just that change probably isn't an option because the input is blurred on every virtual button press, and blur triggers change if there has been some typing too. (Can the user type too with the actual keyboard?) If you must use the change event, the best way is probably to make a custom input wrapper component and emit the change whenever you want.
|
1

When I build any new vue application, I like to use these events for a search input or for other inputs where I don't want to fire any functions on @change

<div class="class">
   <input v-model="searchText" @keyup.esc="clearAll()" @keyup.enter="getData()" autofocus type="text" placeholder="Start Typing ..."/>
   <button @click="getData()"><i class="fas fa-search fa-lg"></i></button>
</div>

These will provide a better user experience in my opinion.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.