Blog>
Snippets

Scoped Provide/Inject for Modals and Dialogs

Create an example where provide and inject are used to pass data to a modal or dialog component that is conditionally rendered, thereby avoiding prop drilling and event emitting.
// ParentComponent.vue
<template>
  <button @click="showModal = true">Open Modal</button>
  <Modal v-if="showModal" />
</template>

<script>
import { provide, ref } from 'vue';
import Modal from './Modal.vue';

export default {
  components: { Modal },
  setup() {
    const showModal = ref(false);
    const modalData = ref({ title: 'Sample Modal', content: 'This is a modal dialog.' });

    provide('modalData', modalData);

    return { showModal };
  }
};
</script>
The ParentComponent uses a 'provide' function to pass 'modalData' to its descendants. A modal is conditionally rendered based on 'showModal' state.
// Modal.vue
<template>
  <div class="modal">
    <h2>{{ data.title }}</h2>
    <p>{{ data.content }}</p>
    <button @click="$parent.showModal = false">Close</button>
  </div>
</template>

<script>
import { inject } from 'vue';

export default {
  setup() {
    const data = inject('modalData');

    // handle case where 'modalData' isn't provided
    if (!data) {
       console.error('modalData is not provided by any ancestor!');
       // fallback or error handling here
    }

    return { data };
  }
};
</script>
The Modal component uses 'inject' to receive 'modalData' from an ancestor, in this case, the ParentComponent. It also handles the case when 'modalData' isn't provided.