javascript - Creating a Dialog component and showinghiding from parent - Stack Overflow

In VueVuetify, how do we hideshow dialogs from parent? I'm trying to use v-model and here is a s

In Vue/Vuetify, how do we hide/show dialogs from parent? I'm trying to use v-model and here is a simplified version of my setup:

Parent ponent (just a button that triggers the child ponent to show)

<template>
<div>
    <v-btn class="ma-2" outlined fab color="red" small @click.stop="editItem()">
        <v-icon size="16">mdi-close-circle</v-icon>
    </v-btn>
    <user-dialog v-model="dialog" :eitem="editedItem" class="elevation-2" />
</div>
</template>

<script>
import UserDialog from "./UserDialog.vue";
export default {
    ponents:{
        UserDialog
    },
    data() {
        return {
            counter: 0,
            dialog: false,
            editedItem: {},
        }
    },
    methods: {
        editItem: function() {            
            this.counter++;       
            this.editedItem = Object.assign({}, {
                title: 'some title' + this.counter,
                details: 'some details for this item'
            });        

            this.dialog = true;
        },
    },
}
</script>

Child ponent (basically a dialog box)

<template>
    <v-dialog v-model="value" max-width="500px">
        <v-card>
            <v-card-title>
                <span class="headline">A Dialog</span>
            </v-card-title>

            <v-card-text>
                <v-container grid-list-md>
                    <v-layout wrap>
                        <v-flex xs12>
                            <v-text-field v-model="eitem.title" label="Title"></v-text-field>
                        </v-flex>
                        <v-flex xs12>
                            <v-text-field v-model="eitem.details" label="Details"></v-text-field>
                        </v-flex>
                    </v-layout>
                </v-container>
            </v-card-text>

            <v-card-actions>
                <v-spacer></v-spacer>
                <v-btn color="blue darken-1" text @click.stop="save">Save</v-btn>
                <v-btn color="blue darken-1" text @click.stop="close">Cancel</v-btn>
            </v-card-actions> 
        </v-card>
    </v-dialog>
</template>

<script>
    export default {
        props: {
            value: Boolean, 
            eitem: Object,
        },
        data() {
            return {
                editedItem: this.eitem,
            }
        },
        methods: {
            save() {
                //perform save
                this.$emit('input', false);
            },
            close() {
                this.$emit('input', false);
            },
        },
    }
</script>

This setup works, but give the following warning:

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

But if act upon this advice and declare a data item in the child ponent and set v-model of the v-dialog to this data item, the dialog stops showing up upon click.

I perhaps understand why it does that, but cannot figure out a proper way of fixing this that doesn't show warnings. Can anyone help me with this?

In Vue/Vuetify, how do we hide/show dialogs from parent? I'm trying to use v-model and here is a simplified version of my setup:

Parent ponent (just a button that triggers the child ponent to show)

<template>
<div>
    <v-btn class="ma-2" outlined fab color="red" small @click.stop="editItem()">
        <v-icon size="16">mdi-close-circle</v-icon>
    </v-btn>
    <user-dialog v-model="dialog" :eitem="editedItem" class="elevation-2" />
</div>
</template>

<script>
import UserDialog from "./UserDialog.vue";
export default {
    ponents:{
        UserDialog
    },
    data() {
        return {
            counter: 0,
            dialog: false,
            editedItem: {},
        }
    },
    methods: {
        editItem: function() {            
            this.counter++;       
            this.editedItem = Object.assign({}, {
                title: 'some title' + this.counter,
                details: 'some details for this item'
            });        

            this.dialog = true;
        },
    },
}
</script>

Child ponent (basically a dialog box)

<template>
    <v-dialog v-model="value" max-width="500px">
        <v-card>
            <v-card-title>
                <span class="headline">A Dialog</span>
            </v-card-title>

            <v-card-text>
                <v-container grid-list-md>
                    <v-layout wrap>
                        <v-flex xs12>
                            <v-text-field v-model="eitem.title" label="Title"></v-text-field>
                        </v-flex>
                        <v-flex xs12>
                            <v-text-field v-model="eitem.details" label="Details"></v-text-field>
                        </v-flex>
                    </v-layout>
                </v-container>
            </v-card-text>

            <v-card-actions>
                <v-spacer></v-spacer>
                <v-btn color="blue darken-1" text @click.stop="save">Save</v-btn>
                <v-btn color="blue darken-1" text @click.stop="close">Cancel</v-btn>
            </v-card-actions> 
        </v-card>
    </v-dialog>
</template>

<script>
    export default {
        props: {
            value: Boolean, 
            eitem: Object,
        },
        data() {
            return {
                editedItem: this.eitem,
            }
        },
        methods: {
            save() {
                //perform save
                this.$emit('input', false);
            },
            close() {
                this.$emit('input', false);
            },
        },
    }
</script>

This setup works, but give the following warning:

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

But if act upon this advice and declare a data item in the child ponent and set v-model of the v-dialog to this data item, the dialog stops showing up upon click.

I perhaps understand why it does that, but cannot figure out a proper way of fixing this that doesn't show warnings. Can anyone help me with this?

Share Improve this question asked Jul 27, 2019 at 13:07 dotNETdotNET 35.5k28 gold badges173 silver badges274 bronze badges 7
  • Instead of using v-model bind the v-text-field's value to the prop. And on input emit a custom event to the parent and let it update the prop's value. You can use a puted property with a getter/setter. – Husam Elbashir Commented Jul 27, 2019 at 13:15
  • @HusamIbrahim: I hear that v-model is a syntactic sugar that does exactly the thing that you described. How'd that approach be different? – dotNET Commented Jul 27, 2019 at 13:17
  • Just to clarify, those text-field bindings are not the issue at hand right now. I'm actually struggling with the v-dialog's v-model at the moment. The gist of the problem in my understanding is that I need a way to bind a local data item with a prop, so that whenever the parent ponent changes its bound data item, the child ponent is notified about this change and in response the child ponent updates its local data item (which will then trigger v-dialog to appear or disappear.. – dotNET Commented Jul 27, 2019 at 13:22
  • The difference is that v-model will attempt to directly modify the value on input and that's the equivalent of @input="value=$event.target.value". What you want is to emit a custom event to the parent via @input="()=>{$emit('updateValue', newValue}" and have the parent listen for an updateValue event to update the value of the prop. That will automatically be reflected in the child ponent after update. – Husam Elbashir Commented Jul 27, 2019 at 13:28
  • I see that you declare value as a prop to be used with v-dialog but you don't pass it's value from the parent. In that case you should specify a default value. And instead of using v-model on the value directly use a puted property with a getter/setter. That way if a value is passed from the parent you can emit a custom event to the parent to update the prop's value. Otherwise you can update a local value instead. – Husam Elbashir Commented Jul 27, 2019 at 13:40
 |  Show 2 more ments

2 Answers 2

Reset to default 5

Since Vue throws a warning when you mutate props, you should not use v-model with props. To handle this use the following pattern:

puted: {
  propModel: {
    get () { return this.value },
    set (value) { this.$emit('input', value) },
  },
},

Define puted property with getter, that returns props.value, and setter that emits input event (that will be successfully handled in parent, since you use v-model)

Don't forget to chage your template: <v-dialog v-model="propModel" max-width="500px">

This works for me and do not need to create a puted data.

<v-dialog
    width="600px"
    :value="value"
    @input="$emit('input', $event)"
  >
    
</v-dialog>

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744108958a4558859.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信