Reputation: 842
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
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
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