Search code examples
javascriptformsobjectvuejs2vue-reactivity

Detecting change in data object members attached to fields via v-model


I have a large-ish Vue app using Vuetify that is comprised primarily of forms, and I need to add the functionality of detecting when a change has been made to the value in any of the form fields so that when a user navigates away from the form and there are unsaved changes, they can be warned. I can handle the setting of values to indicate changes and issuing the warning, but the initial thing I need to do is being able to detect changes in the various fields.

The basic structure is to:

1) Create an object that contains the different values for the form fields:

class Tenant {
  constructor(tenant) {
    this.code = tenant.code || '';
    this.name = tenant.name || '';
    this.defaultPostBack = tenant.defaultPostBack || '';
    this.maxIdentities = tenant.maxIdentities || '';
  }
}

export default Tenant;

2) Define it in the component data:

  data: () => ({
    tenantModel: new Tenant({}),
  })

but can also be updated at other places in the code, such as when a record is retrieved from the back end:

this.tenantModel = new Template({tenant})

3) Bind the object members to the individual fields via v-model:

<v-layout row>
  <v-flex xs6>
    <v-text-field v-bind="fields.defaultPostBack"
      v-model="tenantModel.defaultPostBack" />
  </v-flex>
  <v-flex xs6>
    <v-text-field v-bind="fields.maxIdentities"
      v-model="tenantModel.maxIdentities" />
  </v-flex>
</v-layout>

My initial thought was to do watch on the tenantModel object to catch field changes, but the only time a watch on tenantModel is triggered is when a line like this.tenantModel = new Template({}) is called; changing a value in one of the bound fields doesn't trigger it.

I know one option is to add an @input or @change handler (depending on the field type) for each field, but that's a ton of work, and there are some fields in other places - such as v-combobox fields - that already have listeners for those events.

Is there a way to have some sort of watch on the bound data object? Or am I going to have to add listeners on the individual fields?


Solution

  • Have you tried deep watcher ?

    Created this jsfiddle for your reference https://jsfiddle.net/efqy6pmo/

    Also check out the docs for more options https://v2.vuejs.org/v2/api/#watch

    Reference link: Vue.js - How to properly watch for nested data