10

I have a page in Vue with input fields. I wanna show a message when someone changed any input field in that component. I'm used to Angular where you can use the isDirty function, but Vue doesn't have that.

Is there a way to catch all keyup events in a Vue view? So I can catch that and set a variable to true for the message to be shown?

Now I have this added to all input models: <input v-model="foo" @change="someThingChanged()">

agm1984
  • 15,500
  • 6
  • 89
  • 113
Sanne V
  • 51
  • 1
  • 1
  • 7

4 Answers4

13

Is there a way to catch all keyup events in a Vue view?

You can bind single onchange event on the parent container and benefit from the fact that change events bubble:

<div class="container" @change="someThingChanged()">
  <input v-model="foo">
  <input v-model="bar">
  ... etc.
</div>
dfsq
  • 191,768
  • 25
  • 236
  • 258
  • Nice. Same goes for `@input` which already triggers while typing. Note that (at least for PrimeVue 3) events for Dropdown somehow don't seem to bubble up. – Arjan Jan 25 '21 at 20:28
  • 1
    Keep in mind that `change` events emitted by Vue do NOT bubble, as described in [this question](https://stackoverflow.com/questions/66861657/vue-js-emit-native-dom-events) – Spooky Mar 31 '21 at 19:53
3

I am not that experienced in Vue but watch seems preferable here.

 watch: {
 item: {
    handler(val){
      // do stuff
    },
    deep: true
  }
}
tony19
  • 125,647
  • 18
  • 229
  • 307
Menelaos Vergis
  • 3,715
  • 5
  • 30
  • 46
2

Apart from checking for dirty, We can also use Component Navigation guards to prevent user from navigating elsewhere if the form is dirty. BeforerouteLeave Vue Component route gaurd.

...
data: {
  formDirty: false, 
}
methods: {
  somethingchanged() {
    formDirty = true,
  }
}
beforeRouteLeave (to, from, next) {
  if(formDirty){
    const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
    if (answer) {
      return next()
    } else {
      return next(false)
    }
  }
  return next()
}
...
agm1984
  • 15,500
  • 6
  • 89
  • 113
lokanath
  • 237
  • 6
  • 16
1

Instead of watching the DOM for key or change events, it would be better to just observe foo which is already in the component state. In this case I've used a computed function based on foo:

const app = new Vue({
  el: '#vue-wrapper',
  data: {
    foo: '',
  },
  computed: {
    showMessage() {
      return (!!this.foo) // <-- your logic here
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="vue-wrapper">
  Foo: <input v-model="foo">
  <div v-if="showMessage">This will be shown if foo is not empty</div>
</div>
Daniel Beck
  • 20,653
  • 5
  • 38
  • 53