Eugene Barsky
Eugene Barsky

Reputation: 6012

How to trigger 'change' on <input> changed programmatically

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.

Upvotes: 6

Views: 27901

Answers (2)

Towkir
Towkir

Reputation: 4014

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;
    });
  }
};

Upvotes: 6

primegxy
primegxy

Reputation: 1878

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.

Upvotes: 1

Related Questions