ST80
ST80

Reputation: 3903

Vue how to detect form input changes

In my vue-app I have a form, which should detect each change. I tried to use @change and also with a watcher, but with no luck...

form: {
  name: "",
  surname: "",
  email: "",
},
changed: false

then in my template:

<form @change="hasChanged">

Then my watcher and method:

watch: {
    form: {
        handler: function(v) {
            return this.hasChanged();
        },
        deep: true
    }
},
methods: {
  hasChanged(){
    this.changed = true
  }
}

But this doesn't work.... what am I doing wrong?

Upvotes: 9

Views: 25431

Answers (4)

Funsho
Funsho

Reputation: 81

The answer @Babacar gave is a long process, @ST80, yes the change event works

Here is how to use it,

No need to use a watcher with the form

Add the event to your form tag

<form @change="formUpdated">

then add the function

    formUpdated (): void {
  this.formNotUpdated = false
}

This will work for differntly depending on the input feild type, for example the text input chnage will fire when you click out of the input or you can use a console.log() to test if it logs something when you change a input..Im guessing your use case is for a profile page where you want to disable a button until a form is updated.

check the documentation here https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event

Upvotes: 0

Babacar C. DIA
Babacar C. DIA

Reputation: 420

Form element does not have a change listener. Consider binding each input instead with the onChanged event instead.

From what I am seeing it seems like you want to know if the form has been edited. In that case you can try this


<template>
    <form>
        <input v-model="form.first_name"/>
        <input v-model="form.last_name"/>
        <input v-model="form.email"/>
    </form> 
</template>

<script>
    const defaultForm = {
        first_name: '',
        last_name: '',
        email: '',
    }  
    export default {
      data () {
        return {
            // form: defaultForm
            // edit
            form: {...defaultForm}
        }
      },
      computed: {
        hasChanged () {
          return Object.keys(this.form).some(field => this.form[field] !== defaultForm[field])
        }
      }
    }
</script>

Upvotes: 10

tuhin47
tuhin47

Reputation: 6058

Based on @Babacar answer the hasChanged always return false as the form and defaultForm refer to the same object. The form should be a copy before rendering. We can use a shallow copy for the normal case and the nested object, we need to use the deep copy.

<template>
    <form>
        <input v-model="form.first_name"/>
        <input v-model="form.last_name"/>
        <input v-model="form.email"/>
    </form> 
</template>

<script>
    const defaultForm = {
        first_name: '',
        last_name: '',
        email: '',
    }  
    export default {
      data () {
        return {
            form: {...defaultForm } // copy here
        }
      },
      computed: {
        hasChanged () {
          return Object.keys(this.form).some(field => this.form[field] !== defaultForm[field])
        }
      }
    }
</script>

Upvotes: 2

codeCraft
codeCraft

Reputation: 72

You can use the watch from vuejs, a very simple trick.

watch: {
   'form': {
        handler: function(v) {
         return this.enableFormSubmission();
        },
        deep: true
    }
},

Upvotes: 3

Related Questions