Component isn't display by VueJS if it is inside a v-if/v-show

I’m trying to display a component when I hit a button ‘Add Patient’, by using a v-if :

// between <template></template>
<button type="button" class="btn btn-info" @click="showPatientForm">Add a patient</button>
...
<div class="d-flex flex-column w-75 contentOrder">
    <div class="" v-if="showArticle" ref="patientOk"> <!-- if the patient exists, show the articles -->
        <ArticleCmp/>
    </div>
    <div class="hidden" ref="patientNotOk" v-else> <!-- Else show a form to create a patient -->
        <PatientForm :addPatient="addPatient"/>
    </div>
</div>

// between <script></script>, export default(){ methods:... }

showPatientForm(){
        try{
                const createPatient = this.$refs.patientNotOk // Find the <div> of the form
                createPatient.classList.remove('hidden') // Get rid of the hidden class
            }
        catch(err){
                console.error(err)
        }
},

I know it’s not a clean way to make it works, but if I make the v-else to a v-if, when I show the patient form, and then click on an existing patient, the patient form doesn’t disappears.

But the problem is, that if I want to click on an existing patient and then create a client, this.$refs.PatientNotOk is considered null. That is because VueJS (Vite 3) doesn’t render at the beginning the v-else, as it is not true. So How can I make it render the v-else ?

The error log :


TypeError: createPatient is null
    showPatientForm CreateOrderView.vue:127
    2 CreateOrderView.vue:33
    callWithErrorHandling runtime-core.esm-bundler.js:173
    callWithAsyncErrorHandling runtime-core.esm-bundler.js:182
    invoker runtime-dom.esm-bundler.js:345
CreateOrderView.vue:131:25
    showPatientForm CreateOrderView.vue:131
    2 CreateOrderView.vue:33
    callWithErrorHandling runtime-core.esm-bundler.js:173
    callWithAsyncErrorHandling runtime-core.esm-bundler.js:182
    invoker runtime-dom.esm-bundler.js:345

(line 131 is the console.error of the catch, line 127 is the createPatient.classList.remove and line 33 is the button "Add a patient" in the template)

>Solution :

When using ref, you need to add variables ref with the same names.

const patientNotOk = ref();
const patientOk = ref();

Here is a working script setup :

<script setup>
import { ref } from "vue";
const patientNotOk = ref();
const patientOk = ref();
const showPatientForm = () => {
  try {
    const createPatient = patientNotOk.value; // Find the <div> of the form
    createPatient.classList.remove("hidden"); // Get rid of the hidden class
  } catch (err) {
    console.error(err);
  }
};
</script>

Leave a Reply