Strategies for managing dynamically mounted component events

I have a widget defined as:

Calculator.vue

    <template>
       ...
    </template>
    <script>
    export default {
      data: function () {
        return {
          value: 0,
        };
      },
      methods: {
        ...
        insert() {
          this.$emit('insert',Number(this.value))
        },
      },
    };
    </script>

Now I have another component that displays a Popup which includes my Calculator widget

Main.vue

    <template>
       ...
    </template>
    <script>
    import Calculator from "../../ui/Calculator.vue";
    export default {
      data: function () {
        return {};
      },
      methods: {
        openCalculator() {
          this.$popup("append", {
            component: Calculator,
          });
        },
      },
    };
    </script>

The Popup component is a third-party component that acts as a wrapper. So I always need to include it in my App.vue:

    <template>
      <div id="app">
        <router-view />
        <VuePopupPlugin :config="popupDefaultConfig" />
      </div>
    </template>
    <script>
    import Vue from "vue";
    import CiaoVuePopup from "ciao-vue-popup";
    Vue.use(CiaoVuePopup);
    export default {
      name: "app",
      ...
    };
    </script>

How can I manage the 'insert' event of the displayed Calculator from my Main component?

Answer №1

Implementing Event Handling with $listeners in Vue

If you're not utilizing Vuex, you can still manage event handling in Vue by leveraging the $listeners attribute. Here's how you can achieve this:

Within the intermediate component Popup, capture the event triggered by its child component Calculator. This approach also works with dynamic components. Simply pass the event up to the parent component Main without performing any specific actions. This is where the v-on="$listeners" directive comes in handy:

<!-- Inside `Popup` component -->
<Calculator v-on="$listeners"></Calculator>

Next, in the Main component, define the listener as if Calculator were a direct child component and attach it to the intermediate component, Popup:

<!-- Inside `Main` component -->
<VuePopupPlugin @insert="insert" :config="popupDefaultConfig" />
methods: {
  insert() {
    console.log('Event triggered: Insertion performed');
  }
}

This approach functions because $listeners in Popup retrieves all listeners from its parent component, Main, and applies them to its child component, Calculator, as if the intermediate component didn't exist in the hierarchy. To cascade multiple intermediate components, simply utilize v-on="$listeners" on each of them.

Here's a demonstration:

Vue.component('Calculator', {
    template: `
  <div class="calc">
    CALCULATOR:
    <button @click="insert">Insert</button>
  </div>`,
  data: function () {
    return {
      value: 1000,
    };
  },
  methods: {
    insert() {
      this.$emit('insert', Number(this.value))
    },
  }
})

Vue.component('Popup', {
  template: `
  <div class="popup">
    POPUP:
    <component :is="comp" v-on="$listeners"></component>
  </div>
  `,
    data() {
      return {
        comp: 'Calculator'
      }
    }
});

/***** APP *****/
new Vue({
  el: "#app",
  data() {
    return {
        someEventData: null
    }
  },
  methods: {
    insert(eventData) {
        this.someEventData = eventData;
    }
  }
});
.calc, .popup {
  padding: 24px;
}
.calc {
  background: #dddddd;
}
.popup {
  background: #FF99FF;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  ROOT
  <Popup @insert="insert"></Popup>
  Data from grandchild (calculator): {{ someEventData }}
</div>

To streamline event management across components, consider employing Vuex to establish a centralized store for emitting and retrieving data.

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

Utilize Jquery and MVC 5 to create a reoccurring partial view

I have a button that triggers the loading of a partial view containing a table with all the categories in my system. <input type="button" value="Load Categories" id="btnLoadCategories" /> This loading process is done via a partial view which is in ...

Show the React component once the typewriter effect animation is complete

Hello there, I am looking to showcase my social links once the Typewriter effect finishes typing out a sentence in TypeScript. As someone new to React, I'm not quite sure how to make it happen though. Take a look at the code snippet below: ` import ...

Navigating with React-router can sometimes cause confusion when trying

I'm having trouble with my outlet not working in react-router-dom. Everything was fine with my components until I added the Outlet, and now my navigation component isn't showing even though other components are rendering. import Home from ". ...

Adding HTML attributes to a VueJS table allows for more customization and control

Is it possible to incorporate HTML/Bootstrap elements into a cell in VueJS? <b-table striped show-empty :items="filtered"> <template slot="top-row" slot-scope="{ fields }"> <td v-for="field in fields& ...

Extracting information from an ENORMOUS Array

Let's start with my code snippet, featuring an array: var UserProfiles = [{ userProfileID: 1, firstName: 'Austin', lastName: 'Hunter', email: 'test', token: '', platform: 'android ...

Protractor - Error: prop is undefined

Need assistance in identifying an error. Currently, I am learning Protractor and attempting to create a basic test using Page Object. //login_pageObject.js let loginContainer = function() { this.usernameInput = $("input.login-form-01"); this.passwordInp ...

Having trouble getting an HTML form to function with Ajax and PHP?

Seeking assistance from anyone who can lend a hand. I am delving into the complexities of Ajax, and I'm encountering issues where it seems like the script is being completely ignored or perhaps I'm just making a rookie mistake. Prior to display ...

The back-end code on the server is unable to identify the variable in my req.body, as it is being flagged

At the moment, I am in the process of developing a web application that needs to transmit data from the client side to the server side whenever a specific button is clicked. However, when I click the button, the terminal consistently informs me that the va ...

Increase initial zoom for React Three Fiber OrbitControls to provide a wider view

I've been working on a project in React Three Fiber using this codesandbox for practice. My query regarding the demo is about setting a wider initial zoom in OrbitControls to view more small stars. Can anyone help with this? Below is the code snippe ...

Using aliases in npm packages is not supported

I am working on creating an npm package that I want to use in another application. During development, I set a path in tsconfig for importing various modules instead of using a relative path. However, when I download my package into the test app, it is una ...

Customize the CSS for the column containers in Material-UI's DataGrid with the

I am facing a challenge in trying to override the CSS property position on the .MuiDataGrid-columnsContainer. Upon reviewing the information available on https://material-ui.com/api/data-grid/#css, it seems that there is a rule defined for root but not spe ...

A simple guide on passing a variable from Node.js to the view

Currently, I am delving into the world of Node.js and encountering a hurdle in sending a variable from app.js to index.html without relying on Jade or any other template engine. Below is my implementation in app.js: var express = require("express"); var ...

What are the distinctions in how jQuery behaves when an element is assigned to a variable versus in Javascript?

I've noticed that when I assign a jQuery element to a variable, it doesn't match the element in a comparison. However, if I assign a JavaScript element, it does... test1 = $(".the_div"); console.log(test1 == $(".the_div")); // This logs false ...

How can I use a string argument in JavaScript to sort an array of objects by that specific value?

Currently, I am implementing React and facing a challenge with creating a reusable sorting component. This component is meant to sort an array of objects based on a specific property field. For instance, imagine having an array of objects with properties a ...

Filtering a table with a customized set of strings and their specific order using pure JavaScript

Recently, I've been diving into APIs and managed to create a table using pure vanilla javascript along with a long list of sorting commands that can filter the table based on strings. My goal is to establish an object containing strings in a specific ...

"Having trouble with my Ajax Post - seeking an easy solution

I am having trouble with a simple Ajax post request. Here is my code snippet: <html> <body> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script> var deviceDetails = []; ...

Using Vue.js 2: A guide on connecting to a component's method

Working with a VueJS (v2) component, I encountered an issue with displaying a private array of objects this.private.messagesReceived in a textarea. Despite my efforts to bind the data, Vue seems to block the serialization function from updating when the ar ...

Arranging divs using inline-block display. How to adjust the heights consecutively?

After much searching and attempting, I am still unable to achieve a simple task. My goal is to apply display inline-block to some divs while aligning them in a row, similar to the image below: https://i.sstatic.net/iLhLS.png The issue arises when number ...

Displaying a variable in a live HTML user interface

I have successfully created a Python program that captures data from an Arduino Potentiometer and shows it on the Python console. Now, I am working on enhancing the output by displaying it in a local HTML file. I am seeking guidance on how to incorporate t ...

Unable to load custom package in Angular 2 testing environment

I've been following the official Angular 2 testing guide on an existing project. Everything runs smoothly when I use my custom library, downloadjs, in the application. However, I encounter an error in the console during test execution: "__zone_symbol ...