skip to Main Content

I have a component A,there is a dialog in this component A .I want to use visible property to control the visible of dialog.

Component A:

<template>
    <dialog :visible="visibleProp"/>
</templage>
<script setup>
const visibleProp= ref(true)
<script>

Dialog:

<template>
    <dialog  v-model="visible"></dialog>
</templage>
<script setup>
const prop = defineProps(['visible'])
<script>

note:dialog is another component.

I get this error

v-model cannot be used on a prop, because local prop bindings are not writable.Use a v-bind binding combined with a v-on listener that emits update:x event instead.
this is may caused by props should be considered readonly within the component.

How can I change my code to achieve my goal?Thanks a lot!

2

Answers


  1. Vue3 SFC Playground

    Use v-model correctly – update it with a dedicated event. You can’t change component props directly – they are read-only. In your case I suggest to name your v-model visibility to make it more explicitly. Refer to the Vue’s documentation:

    https://vuejs.org/guide/components/v-model.html

    If you use a HTML native dialog you should watch your prop and call methods on the dialog’s ref.
    I strongly recommend to use the native HTML dialog due much better keyboard navigation and accessibility.

    App.vue:

    <script setup>
    
    import MyDialog from './MyDialog.vue';
    import {ref} from 'vue';
    const visible = ref(false);
    
    </script>
    <template>
      <button @click="visible=true">Show dialog</button>
      <my-dialog v-model:visible="visible">
        <template #title>My Dialog</template>
        Testing v-model for the dialog's visibility
      </my-dialog>
    </template>
    

    MyDialog.vue

    <script setup>
    
    const props = defineProps({visible:Boolean});
    
    import {ref, watch, onMounted} from 'vue';
    const $dialog = ref();
    
    onMounted(() => {
        watch(() => props.visible, val => val ? $dialog.value.showModal() : $dialog.value.close(), {immediate:true});
    });
    
    </script>
    <template>
    <dialog @close="$emit('update:visible', false)" ref="$dialog">
        <h2><slot name="title"></slot></h2>
        <p><slot></slot></p>
        <button @click="$dialog.close()">Close</button>
    </dialog>
    </template>
    
    Login or Signup to reply.
  2. Dialog

    <template>
        <dialog  v-model="visible"></dialog>
    </templage>
    <script setup>
    import { computed } from 'vue'
    const prop = defineProps(['visible'])
    const emits = defineEmits(['update:visible'])
    const visible = computed({
      get() {
        return prop.visible
      },
      set(value) {
        emits('update:visible', value)
      }
    })
    </script>
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search