typescriptvuejs3dialogquasar

TypeError: Cannot set properties of undefined (setting 'value') in vuejs3


I want to add a dialog component to my tableConfig.vue but it keep giving me this error: Cannot set properties of undefined (setting 'value') TypeError: Cannot set properties of undefined (setting 'value') at openDialog this is my dialog.vue component

<template>
 <div id="q-app" style="min-height: 100vh;">
  <div class="q-pa-md q-gutter-sm">
  <q-dialog v-model="prompt" persistent>
    <q-card style="min-width: 350px">
      <q-card-section>
        <div class="text-h6">Your address</div>
      </q-card-section>

      <q-card-section class="q-pt-none">
        <q-input dense v-model="address" autofocus @keyup.enter="prompt = false"></q-input>
      </q-card-section>
     </q-dialog>
    </div>
   </div>
 </template>

 <script setup lang="ts">
 import { ref } from 'vue';

 const prompt = ref(false);
 const address = ref('');

</script>

and this is where i want to use the dialog component :

        <template>
        <div class="q-pa-md">
        <q-table
            flat
            bordered
            title="Treats"
            :rows="rows"
            :columns="columns"
            row-key="name"
            :visible-columns="visibleColumns"
        >
                <!-- Add Button Inside q-select -->
                <q-btn
                flat
                round
                dense
                icon="add"
                @click= "openDialog"
                /> 
        </q-table>
        </div>
    </template>
    
    <script setup lang="ts">
    import { ref } from 'vue';
    import MyDialogComponent from './addElement.vue';

    const openDialog = () => {

        MyDialogComponent.prompt.value = true;
    }; 
    </script>

Solution

  • You don't seams to be using your dialog inside your parent template. You should try to address this issue first.

    After that, rather than trying to access a child component's property directly, you should rely on props. It usually goes like this:

    The parent component will define a reactive value and will pass this value, in a props, to it's child component

    <!-- parent component -->
    
    <template>
      <ChildComponent :the-props="reactiveValue" />
    </template>
    
    <script setup>
      const reactiveValue = ref(false);
    </script>
    

    Then, the child component will define a props, to retrieve the value sent by the parent, and emit and events when it wants to mutate the props. This can be done easily by using a writable computed property.

    <!-- ChildComponent -->
    <template>
      <input v-model="propsModel" />
    </template> 
    
    <script>
      const props = defineProps(['theProps']);
      const emit = defineEmits(['update:modelValue']);
      
      const propsModel = computed({
        get() {
          return props.theProps;
        },
        set(value) {
            emit('update:modelValue', value);
        }
      })
      
    </script>
    

    As you can see, when the input mutate the propsModel, the child component will emit an event ( update-the-props ), with the new value.

    We can, then, listen to this event in the parent component and update the reactive value

    <!-- parent component -->
    
    <template>
      <ChildComponent :the-props="reactiveValue" @update-the-props="handleThePropsUpdate" />
    </template>
    
    <script setup>
      const reactiveValue = ref(false);
    
      const handleThePropsUpdate = value => {
        reactiveValue.value = value;
      }
    </script>
    

    In your particular case, this allows the parent component to toggle the visibility of your dialog, without having to rely on the inner working of said dialog.