Vue - when multiple parents share a common child component

Is there a way in Vue.js for multiple parents to share the same child component?

I am looking to have multiple delete buttons trigger a single modal with different content.

For example:

myfile.html:

<table id="app" class="table table-striped table-sm table-responsive-md">
    <thead>
        <tr>
            <th>Title</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        <tr class="post">
            <td>Test2</td>
            <td>
                <delete-confirm popup-title="Are you sure ?" popup-message="Message 1">
                    Delete
                </delete-confirm>
            </td>
        </tr>
        <tr class="post">
            <td>Test article</td>
            <td>
                <delete-confirm popup-title="Are you sure ?" popup-message="Message 2">
                    Delete
                </delete-confirm>
            </td>
        </tr>
    </tbody>
</table>

app.js:

require('./bootstrap');

window.Vue = require('vue');

Vue.component('delete-confirm', require('./components/DeleteConfirm.vue'));
Vue.component('magnific-popup', require('./components/MagnificPopup.vue'));

const app = new Vue({
    el: '#app'
});

components/DeleteConfirm.vue:

<template>
    <span>
        <button ref="button" @click="showConfirmation($event.target)" class="btn btn-danger">
            <i class="fa fa-trash"></i> <slot></slot>
        </button>

        <magnific-popup v-on:click="click" ref="popup">
            <h2 slot="title">{{ popupTitle }}</h2>
            <p slot="content">{{ popupMessage }}</p>
        </magnific-popup>
    </span>
</template>

<script>
    import $ from 'jquery';

    export default {
        props: ['popupTitle', 'popupMessage'],
        methods: {
            showConfirmation(target) {
                this.$refs.popup.open(target);
            },
            click(type) {
                this.$refs.popup.close();

                if (type === 'confirm') {
                    $.ajax({
                        url: '404me',
                        type: 'DELETE',
                    }).then(() => { /* TODO */ }).catch(() => { /* TODO */ });
                }
            }
        },
    };
</script>

components/MagnificPopup.vue:

<template>
    <div class="white-popup zoom-anim-dialog mfp-hide">
        <div class="container bg-light col-8 mx-auto p-3 rounded">
            <slot name="title"></slot>
            <div class="popup-content">
                <slot name="content"></slot>
            </div>
            <div class="popup-actions">
                <button type="button" @click="sendYes" class="btn btn-primary">
                    Yes
                </button>
                <button type="button" @click="sendNo" class="btn btn-secondary">
                    No
                </button>
            </div>
        </div>
    </div>
</template>

<script>
    import $ from 'jquery';
    require('magnific-popup');

    export default {
        methods: {
            sendYes() {
                this.$emit('click', 'confirm');
            },
            sendNo() {
                this.$emit('click', 'cancel');
            },
            close: function() {
                $.magnificPopup.close();
            },
            open: function(trigger) {
                $.magnificPopup.open({
                    items: {
                        src: this.$el,
                    },
                    midClick: true,
                    mainClass: 'my-mfp-zoom-in',
                    fixedContentPos: false,
                    fixedBgPos: true,
                    overflowY: 'auto',
                    closeBtnInside: true,
                    preloader: false,
                    removalDelay: 300,
                });
            },
        }
    };
</script>

<style lang="scss">
    @import '~magnific-popup/src/css/main';
    @import '../../css/magnific-popup.css';
</style>

Although it functions properly, one magnific-popup element is created per button component which is inefficient.

Here is the generated HTML code demonstrating the issue better.


It would be ideal not to have to declare a <magnific-popup> in each file that uses the <button-delete> component (e.g. in myfile.html).

Is there a method to include the popup component as a dependency so that it is added once to the DOM and can be reused later on?


What I want to achieve is something like this:

Only <delete-confirm> elements declared in myfile.html, without <magnific-popup> present.

Declare MagnificPopup as a dependency of DeleteConfirm so that whenever one or more <delete-confirm> elements are used, a single <magnific-popup> element is added to the DOM of myfile.html.

Answer №1

To ensure that your <magnific-popup> component is globally accessible, register it in your main.js file (or wherever you initialize your root Vue instance). By registering the component this way, it will only be registered once but will be available to all child components.

Although you haven't included a working example in your question, in my local tests, I found that only one modal/popup is generated instead of multiple overlapping ones.

// main.js

// Register the popup component...
import MagnificPopup from '@/components/MagnificPopup'
Vue.component('magnific-popup', MagnificPopup)

// ...right before creating the Vue instance
new Vue({
  el: '#app',
  router,
  store,
  //...
})

Answer №2

To enhance user experience, place the pop-up at the same level as the buttons labeled button-delete. When clicked, each button should trigger an event using $emit that can be handled by the parent component to perform specific actions on the pop-up.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Best practices for storing non-reactive and static data in a Vue application

Welcome to the community! I'm excited to ask my first question here on StackOverflow. I am currently working with vue.js-v2 and webpack. My goal is to ensure that data remains immutable for child components, which are loaded through the vue-router. T ...

Is there a way to exit from await Promise.all once any promise has been fulfilled in Chrome version 80?

Seeking the most efficient way to determine which server will respond to a request, I initially attempted sending requests in sequence. However, desiring to expedite this probing process, I revised my code as follows: async function probing(servers) { ...

Using Parseint in a Vue.js method

For instance, let's say this.last is 5 and this.current is 60. I want the sum of this.last + this.current to be 65, not 605. I attempted using parseInt(this.last + this.current) but it did not work as expected. <button class="plus" @click="plus"&g ...

Navigating through the Express.js routes incorrectly

I currently have 3 different express.js routes set up: app.get('/packages/:name', (req, res) => {...}); app.get('/packages/search/', (req, res) => {...}); app.get('/packages/search/:name', (req, res) => {...}); At t ...

Execute function when button is clicked in ExpressJS

I am looking to execute a function on my node server when a button on my website is clicked: What I currently have: Index.html (I have not included the entire content for simplicity) <button id="tv">tv</button> Client.js (Client side) const ...

Compiling with GatsbyJs throws an abrupt token error with 'if' being an unexpected token

I am working on a code snippet in GatsbyJS where I am extracting data from a StaticQuery using GraphQL and then rendering a component. The challenge I am facing is to conditionally check if a specific sub-object exists within the data object, and if it doe ...

Vue: Utilizing computed properties to monitor changes in offsetHeight of elements

I am working on a component that requires an array of 50 objects to be passed as a prop. <template> <div v-for="(item,index) in items" ref="items" :key="index"gt; // </div> </template> props: ...

Issue with Vue.js: @input directive not functioning properly in conjunction with v-for directive

I've been working on developing my own custom <input> Vue component. I've implemented a feature that prevents users from inputting the wrong type of data by using regex.test() for each input field. Below is the code snippet for my Vue comp ...

Google Analytics in Next.js Missing Page Title Configuration

I recently set up Google Analytics on my Next.js website, but I'm encountering a strange issue where the analytics are not detecting my webpages and showing as (not set). Everything else seems to be functioning properly. I've double-checked that ...

Flaw in Basic Function Logic Using HTML, JavaScript, and CSS

Need some help with the function onBall3Click1 (code is at the bottom). The ball should act like a lightbulb: ON - turn YELLOW, OFF - turn GRAY. I've been trying to figure out the logic behind it for so long and can't seem to find the issue... ...

The error message "TypeError: res.response is undefined" is indicating

Currently, I am implementing user authentication using JWT auth within a Vue/Laravel single-page application. The problem arises in the register module as it fails to respond upon clicking the button. Upon inspecting the Firefox developer edition's co ...

Node server encountering issue with undefined data in POST request

I have been working on an Angular2/Node.js application. Everything seems to be working fine when I retrieve an object from the Node server, but I'm facing an issue when trying to post data to the server. The request.body always shows as undefined. Can ...

Managing traffic in Google Kubernetes Engine (GKE)

I am encountering an issue with our website deployment on GKE, which consists of 10 pods. When deploying a new version, we use MAXsurge=1 and MAXunavailable=0. Upon trying to access the website during a new deployment, I sometimes only see the header in t ...

The state of my React components keeps disappearing

Within my code, I have implemented a click event on the InterestBox to trigger updates in its appearance and alter the state of its parent container. However, despite inspecting the element using React Developer Tools and attempting API requests, the stat ...

Remove buttons from carousel elements in React Multi-Carousel

Is there a way to hide the arrows in the react-multi-carousel component? https://i.stack.imgur.com/V1nix.png ...

Is there a way to execute a callback function once the page has finished loading through AJAX in

I'm in need of a way to attach new events and execute certain functions on a webpage that loads dynamically. Unfortunately, the resources I've found so far are outdated or lack necessary details (even the jqm docs). My current setup involves jQue ...

JavaScript, AJAX rapid iteration

I am working with some ajax code: $(document).ready( function() { $("#button1").click( function() { $.ajax({ type: "POST", url: "update.php", }); }); }); In my HTML code, I have 200 buttons. How can I ...

Effortlessly executing POST actions in Yii2 Advanced Template REST API

Hey there! I'm facing a challenge that I need some help with. I am currently working on integrating an API into my Yii2 advanced template to allow my WordPress website to send data to my Yii2 app. Here is the setup of my system: 1) Yii2 advanced templ ...

Guide to importing an npm package into a client-side file

Having some trouble importing the js-search npm package into my client-side .js file. The documentation suggests using import * as JsSearch from 'js-search';, but I keep getting a Uncaught TypeError: Failed to resolve module specifier "js-se ...

Update Button Visibility Based on State Change in ReactJS

Currently, I'm utilizing a Material UI button within my React application. Despite changing the state, the button remains visible on the screen. Here's the relevant code snippet: function MainPage() { const state = useSelector(state => sta ...