Do not directly change a prop's value as it will be replaced when the parent component re-renders. Use v-form instead

I'm currently in the process of developing an app using nuxt along with vuetify 2.x, and I keep encountering a specific error message:

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"

My Goal: To disable a submit button on the parent component based on the 'valid' value from a form on a child component.

Here is a snippet 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>

Despite my efforts to avoid directly mutating the prop value in the child component by utilizing onChange and emitting the value to the parent component, I still cannot resolve this issue. Can someone point out where I might be going wrong?

Answer №1

It seems that the issue arises from the utilization of v-model="valid" in the childComponent. Since 'valid' is closely tied to the model, it must be allowed to be altered freely. However, given that it is a prop's value, directly modifying it isn't feasible.

One possible approach would be to tailor the childComponent to incorporate v-model functionality. This way, we could employ the childComponent within the parent component as illustrated below:

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

Answer №2

Set up a new child data element specifically for binding purposes, and initialize it using the prop:

export default Vue.extend({
  props: {
    myData: {
      type: Object,
      default: {},
    },
    isValid: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      validationRules: {
        required: (value: any) => !!value || 'required',
      },
      copiedData: this.myData
    };
  },

Then, make sure to update the v-model in the template section accordingly:

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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

A guide on defining global TypeScript interfaces within Next.js

In the process of developing an ecommerce web application with next.js and typescript, I found myself declaring similar interfaces across various pages and components. Is there a method to create global interfaces that can be utilized by all elements wit ...

Struggling to get my React Typescript styled component slider to function within the component

Check out my demo here I created a simple react application using TypeScript and styled components. The main feature is a slider that adjusts the height of a red box. The red box is a styled component and I pass the height as a prop. Everything was fun ...

3 Ways to Ensure Your Picture Uploads are Visible Right Away

I am currently working on an Ionic app that enables users to upload images to Firebase storage. One issue I am encountering is that the image only changes once a new one is selected, after closing and reopening the app. I would like it to update immediatel ...

Creating a personalized state object containing unresolved promises in React Native utilizing axios inside a custom React Hook

I'm currently in the process of creating a custom state within a custom Hook for React Native (non-Expo environment). The state I am working on looks like this: interface ResponseState { api1: { error: boolean; errorMsg?: string; ...

Extending a type by adding properties from separate files using TypeScript

I am faced with a situation where I have a file containing either a type or interface variable (all of which are exported), and I need to add new properties to this variable from different files without using extends. Essentially, making changes to the sam ...

Top method for transitioning FontAwsome stars class from regular to solid

How can I dynamically change the class of 5 stars of FontAwesome Icons from regular to solid based on a numeric variable level that ranges from 0 to 5? <template> <div id="five-stars"> <font-awesome-icon v-for="(inde ...

Creating a CSS grid layout with an unspecified number of columns all set to equal width

Currently, I am in the process of designing a navigation bar using grids. In essence, when the user is an admin, there should be two additional links at the end of the bar. These links need to have the same width and should not be affected by the amount of ...

Firebase: The Firebase application under the name '[DEFAULT]' is already present (app/duplicate-app)

My Nuxt/Vue.js application requires me to export various Firestore-related elements instead of just firebase.firestore(). Despite this, I am encountering an error stating Firebase App named '[DEFAULT]' already exists (app/duplicate-app) with the ...

VueJS computed property not updating correctly

My web application, built with Laravel / Vue JS, includes a google map component and a Vuetify data-table component. The Vue instance also features a computed property that calculates points for the Google Map based on another computed property from the Vu ...

Transmit information using the buttonRenderer feature in Ag-Grid for Angular applications

Struggling to transfer data between two unrelated components by clicking on a cell in ag-Grid and passing the data to a form component. I utilized the buttonRenderer function to extract row data from ag-Grid, but I'm unsure how to pass it to the secon ...

How to show the raw image content-type using Vue.js

When retrieving an image from a REST API through an HTTP GET with a request body, I have successfully verified the returned content using node.js and chai.js: expect(res).to.have.header('Content-Type', 'image/jpeg'); expect ...

Anonymous function's return type

Looking for advice on an anonymous function I've written: static oneOf(options: any[], cb?: Function) ValidatorFn { .... } I'm a TypeScript beginner and unsure how to specify that the 'cb' must return a boolean. Can this be done, an ...

A comprehensive guide to utilizing Vue for navigating between various pages and showcasing their corresponding titles and text

I am currently developing a blog website using vue.js. My current challenge is as follows: The website has two main pages - one for displaying all the blogs and another for viewing a specific blog post. I am utilizing vuex to manage the state of my applic ...

Guide on importing TypeScript types into Vuetify 3

Exploring the use of the ValidationRule type from the Vuetify library (check out the docs and source code), I'm facing difficulties importing it into my Vue.js component. I have attempted to import the type in different ways, such as: import type { V ...

Using InnerHTML in Javascript within the Quasar/VueJS framework is unsupported

I am looking to dynamically create tables based on the items inside the 'counts' array below. The number of tables and their contents can change. Here is my divContainer, where the innerHTML will be appended: <div id="divContainer" style="pa ...

A guide to confirm if an object includes an HTML element without compromising safety

When I implement a function that is triggered by a click event: useEffect(() => { document.addEventListener('click', (e) => handleClickOutside(e), true); }); The function itself: const myElement = useRef(null); const handleCli ...

Displaying a segment of information extracted from a JSON array

I'm currently tackling a project that involves using React, Redux, and TypeScript. Within the JSON file, there is a key-value pair: "data_start": "2022-09-02" Is there a way to display this date in a different format, specifical ...

What is the reason behind Vue's decision not to cache method results?

Vue introduces the concept of Computed Properties that are only re-evaluated when their dependencies change. For example: computed: { foo() { return this.bar + this.baz; } } <div>{{ foo }}</div> This Computed Property recalculates onl ...

Refresh the table following the removal of an item

I am currently working on displaying server data in a table. The delete function is functioning properly, but the deleted item only disappears from the table after refreshing the page. Is there a way to trigger a re-render of the component after deleting a ...

Tips for altering attributes in a child element produced through v-for in VueJs 3

In my coding setup, the parent component generates child components using the v-for directive: <div class="planlist"> <ul id="planOl"> <PlanLego v-for="action in store.plan" :v-if="actio ...