AllenC
AllenC

Reputation: 2754

Vuetify dialog set prop mutation from child to parent

I'm currently opening a dialog component using this

Parent

<v-btn color="#EF5350" dark small absolute top right fab 
 @click="showDialog">

   <v-icon>zoom_in</v-icon>  

</v-btn>

<UIDialog :dialog="dialog" @updateDialog="dialog = $event" />

<script>
  import UIDialog from '@/components/UI/UIDialog';
  export default {
    data() {
      return {
        dialog: false
      }
    }
    components: {
      UIDialog
    }, 
    methods: {
      showDialog() {
         this.dialog = true;
      }
    }
  }
</script>

This opens the dialog since I set dialog to true

Child

<v-dialog v-model="dialog" fullscreen scrollable>
  <v-card>
     This is a test
  </v-card>
</v-dialog>

<script>
 export default {
   props: {
     dialog: { type: Boolean, default: false }
   }, 
   watch: {
     dialog(val) {
       if (!val) this.$emit('updateDialog', false)
     }
   }
 }
</script>

I use watch since vue dialog doesn't have event. I managed to close the dialog but I'm still getting

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

Upvotes: 6

Views: 3473

Answers (4)

elvonkh
elvonkh

Reputation: 117

Use :value and @input instead of declaring prop to v-model

Prop mutation error happens because v-model have already :value and its mutator, which is triggers this error. If you will use simple :value and declare for @input method close() it will work

Upvotes: 0

Jordan Lundgren
Jordan Lundgren

Reputation: 273

This worked for me:

Parent

<app-my-dialog :dialog="doShowDialog" @close="doShowDialog = false"></app-my-dialog>

Child component (app-my-dialog)

<template>
  <v-dialog :value="showDialog" @click:outside="close()">
    <v-btn @click="close()">Close</v-btn>
  </v-dialog>
</template>
<script>
  export default {
    props: {
      dialog: {
        type: Boolean,
        default: false
     }
    }, 
    computed: {
      showDialog() {
        return this.dialog;
      }
    },
    methods: {
      close() {
        this.$emit('close')
      },
    }
  }
</script>

Note that if you use <v-dialog :persistent="true" ... (that means the dialog won't close on click outside itself), you can omit the @click:outside="close()"

Upvotes: 1

Screll
Screll

Reputation: 286

Decompose your v-model on UIDialog, in favor of

<v-dialog v-bind:value="dialog" v-on:input="emitOutput">

where emitOutput outputs a 'value' event

emitOutput(value) { this.$emit('input', value) }

-- This should handle the message of prop mutation in the console and also provide component level visibility control. You won't need to do any handling for custom events on the parent when emitting an 'input' event.

Upvotes: 0

AllenC
AllenC

Reputation: 2754

I managed to solve my problem by using computed property to get and set the dialog

Child

<v-dialog v-model="dialog" fullscreen scrollable>
  <v-card>
     This is a test
  </v-card>
</v-dialog>

<script>
 export default {
   props: {
     dialog: { type: Boolean, default: false }
   }, 
   computed: {
     dialogState: {
        get() { 
          return this.dialog;
        }, 
        set(val) {
          this.$emit('updateDialog', false);
        }
     }
   }
 }
</script>

Upvotes: 2

Related Questions