Anuj Kaithwas
Anuj Kaithwas

Reputation: 842

Avoid mutating a prop directly error in Vuetify Dialog box

I have created a child component which is a dialog box to which I am passing the prop dialog from a parent component. I am not able to close it because changing the prop value gives a warning. What is the actual way to achieve this?

<template>
  <div>
    <v-dialog v-model="dialog" max-width="290" persistent>
      <v-card>
        <v-card-title class="headline">
          {{ order.fullname }}
        </v-card-title>

        <v-card-text> {{ order.address }} </v-card-text>

        <v-card-actions>
          <v-spacer></v-spacer>

          <v-btn color="green darken-1" text @click="dialog = !dialog">
            Disagree
          </v-btn>
        </v-card-actions>
      </v-card>
    </v-dialog>
  </div>
</template>

<script>
export default {
  name: "EditOrder",
  props: ["order", "dialog"],
  data() {
    return {
      dialogCta: this.dialog,
    };
  },
  methods: {
    closeDialog() {
      // console.log(this.dialog);
      this.dialogCta = !this.dialog;
      console.log(this.dialogCta);
    },
  },
};
</script>

Upvotes: 2

Views: 831

Answers (2)

Adarsh Mohan
Adarsh Mohan

Reputation: 1394

<v-dialog v-model="dialog" max-width="290" persistent>
...
<v-btn color="green darken-1" text @click="dialog = !dialog">

In those lines you are modifying the dialog prop

<template>
  <div>
    <v-dialog v-model="dialogCta" max-width="290" persistent>
      <v-card>
        <v-card-title class="headline">
          {{ order.fullname }}
        </v-card-title>

        <v-card-text> {{ order.address }} </v-card-text>

        <v-card-actions>
          <v-spacer></v-spacer>

          <v-btn color="green darken-1" text @click="dialogCta = false"> <!--  here is your problem ( you are modifying a prop ) -->
            Disagree
          </v-btn>
        </v-card-actions>
      </v-card>
    </v-dialog>
  </div>
</template>

export default {
  name: "EditOrder",
  props: [ "order", "dialog" ],
  data() {
    return {
      dialogCta: false
    }
  },
  watch: {
    dialog: {
      immediate: true,
      handler () {
        this.dialogCta = this.dialog
      }
    }
  },
  methods: {
    closeDialog() {
      console.log(this.dialogCta)
    }
  }
};

Upvotes: 1

Majed Badawi
Majed Badawi

Reputation: 28434

Instead of modifying the prop directly, you can create a computed property that represents the value from the parent, and emits an event on change to close it from the last. Here is a demo:

const dialogmodel = Vue.component('btn', {
  template: '#dialogmodel',
  props: { order: Object, value: Boolean },
  computed: {
    dialog: {
      get () { return this.value; },
      set (value) { this.$emit('close', value); }
    }
  }
});

new Vue({
  el:"#app",
  vuetify: new Vuetify(),
  components: { dialogmodel },
  data: () => ({ order: { fullname:"fullname", address:"address" }, dialog: true }),
  methods: {
    closeDialog(value) { this.dialog = value; }
  }
});
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.js"></script><link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet">

<template id="dialogmodel">
  <div>
    <v-dialog v-model="dialog" max-width="290" persistent>
      <v-card>
        <v-card-title class="headline">
          {{ order.fullname }}
        </v-card-title>
        <v-card-text> {{ order.address }} </v-card-text>
        <v-card-actions>
          <v-spacer></v-spacer>
          <v-btn color="green darken-1" text @click="$emit('close')">
            Disagree
          </v-btn>
        </v-card-actions>
      </v-card>
    </v-dialog>
  </div>
</template>

<v-app id="app">
  <dialogmodel v-model="dialog" :order="order" @close="closeDialog" />
</v-app>

Upvotes: 2

Related Questions