0

My question is simple. I have a form where a user can edit the entry in a Nuxt/Vue app. Now I want to disable the submit button until the form field's values have not changed. I use Vuex store to get the entry.

// store/users.js

export const state = () => ({
  currentCustomer: null,
})

export const actions = {
  async fetchCustomer({ commit }, customerId) {
    const customer = await this.$strapi.$customers.findOne(customerId)
    commit('setCurrentCustomer', customer)
  }
}

export const mutations = {
  setCurrentCustomer(state, customer) {
    state.currentCustomer = customer
  },
}

Here is my Vue/Nuxt Template:

<template>
    <section class="d-flex flex-column mb-5">
      <b-form v-else class="border rounded bg-white p-4 shadow-sm" @submit.stop.prevent="saveUser">
        <b-form-group class="capital" label-for="name">
          <template v-slot:label> Name <span class="text-danger">*</span> </template>
          <b-form-input id="name" v-model.trim="form.name" type="text" autofocus required></b-form-input>
        </b-form-group>

        <b-form-group class="capital" label-for="email">
          <template v-slot:label> Email <span class="text-danger">*</span> </template>
          <b-form-input id="email" v-model.trim="form.email" type="email" required></b-form-input>
        </b-form-group>

        <p>Changed: {{ changed }}</p>

        <code>Actual: {{ actual }}</code>

        <code>Form: {{ form }}</code>

        <b-row>
          <b-col>
            <button type="submit" :disabled="!changed">Save</button>
          </b-col>
        </b-row>
      </b-form>
    </section>
</template>

<script>
export default {
  data() {
    return {
      changed: false,
    }
  },
  computed: {
    form() {
      return this.$store.state.users.currentCustomer
    },
    actual() {
      return this.$store.state.users.currentCustomer
    },
  },
  watch: {
    form(newValue) {
      this.changed = newValue !== this.actual
    },
  },
  created() {
    this.$store.dispatch('users/fetchCustomer', this.$route.params.id)
  },
}
</script>

The above code is not working. I know that something needs to be watched but I can't get my head around this issue. I would appreciate any help.

9
  • why you need it? Commented Jan 26, 2021 at 13:47
  • and why you cannot simply register a onchange event listener? (is it a vue.js limitation?) Commented Jan 26, 2021 at 13:48
  • developer.mozilla.org/en-US/docs/Web/API/HTMLElement/… Commented Jan 26, 2021 at 13:54
  • I need it because it is a better UX practice to let a user know whether he has made any change ore not. Can you please explain how onchange event can help to achieve this? Commented Jan 26, 2021 at 13:57
  • you receive onchange event, then set changed to true. Commented Jan 26, 2021 at 13:58

2 Answers 2

3

for object value, add a deep in watch, also, you need lodash.isEqual() to compare if two objects are equal

import _ from 'lodash';

...
    watch: {
      form: {
        handler(value){
          if(value) {
            this.changed = !_.isEqual(value, this.actual);
          }
        },
        deep: true,
      }
    },
...
Sign up to request clarification or add additional context in comments.

Comments

0

Try to use @change="onChangeFn" or v-on:change="onChangeFn" on

methods: {
  onChangeFn () {
    this.changed = true
  }
}

1 Comment

What if a user changes a field value and then reverts back the change. This doesn't handle that usecase.

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.