0
votes

I am building an app with nuxt (using vuetify 2.x). and keep getting this error

Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "isFormValid"

What I am trying to do: Disable a submit button on parent component depending on 'valid' value on the form on child component.

Here's part of my code:

parent.vue

<template>
....
    <v-stepper-items>
      <v-stepper-content step="1">
        <ChildComponent :somedata="somedata" :valid="isFormValid" @onChange="update" />
        <v-btn color="primary" @click="dosomething" :disabled="!isFormValid"> submit </v-btn>
      </v-stepper-content>
    </v-stepper-items>
...

</template>

<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
  components: {
    ChildComponent,
  },
  data() {
    return {
      isFormValid: false,
      step: 1,
      somedata: {}
    };
  },
  methods: {
    update(val: boolean) {
      this.isFormValid = val;
    }
  },
});
</script>

childComponent.vue

<template>
  <v-container>
    <v-card flat>
      <v-card-text>
        <v-form v-model="valid" @change="onChange" class="pa-3">
          <v-text-field v-model="somedata.aaa" label="a" :rules="[rules.required]" />
          <v-text-field v-model="somedata.bbb" label="b" :rules="[rules.required]" />
        </v-form>
      </v-card-text>
    </v-card>
  </v-container>
</template>


<script lang="ts">
import Vue, {PropType} from 'vue';

export default Vue.extend({
  props: {
    somedata: {
      type: Object,
      default: {},
    },
    valid: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      rules: {
        required: (value: any) => !!value || 'required',
      },
    };
  },
  methods: {
    onChange() {
      this.$emit("onChange", this.valid);
    }
  }
});
</script>

I know that I get this error when child component directly mutates the prop value but that is why I added onChange on v-form and emit the value to the parent component. but it still does not work.

Can anyone see what I am doing wrong?

2
v-model="valid" is still binding the @input event to the prop. change to :value="valid"Igor Moraru

2 Answers

0
votes

As far as I know, the problem is because of v-model="valid" in childComponent. As valid is bind to the model, it needs to be free to be changed, but as it is the props value, we can't change the value directly.

My suggestion is to customize childComponent to have v-model. So we can use childComponent in parent component like this

<ChildComponent :somedata="somedata" v-model="isFormValid" />
0
votes

Create a separate child data element for binding, and initialize it with the prop:

export default Vue.extend({
  props: {
    somedata: {
      type: Object,
      default: {},
    },
    valid: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      rules: {
        required: (value: any) => !!value || 'required',
      },
      somedataCopy: this.someData
    };
  },

and update the template v-model:

<template>
  <v-container>
    <v-card flat>
      <v-card-text>
        <v-form v-model="valid" @change="onChange" class="pa-3">
          <v-text-field v-model="somedataCopy.aaa" label="a" :rules="[rules.required]" />
          <v-text-field v-model="somedataCopy.bbb" label="b" :rules="[rules.required]" />
        </v-form>
      </v-card-text>
    </v-card>
  </v-container>
</template>