"Communication breakdown in Vue.js: $emit event not being picked up by corresponding $

Vue.component('rating-edit', {
    template:`
    <form>
      <input v-model="rating.title" type="text">
      <textarea v-model="rating.remark">{{rating.remark}}</textarea>
      <button type="button"
        @click="submit">
        Save
      </button>
    </form>`,
    props:['rating'],
    methods: {
      submit: function submit () {
        let rating = this.rating;
        this.$emit('submit', rating);
        console.log('submit was emitted');
      }
    }
  });

const aRating = {
    title: 'title',
    remark: 'remark'
  };

let vueApp = new Vue({
    el: '#rating-edit-container',
    data: {
      rating: aRating
    }
  });

vueApp.$on('submit', function(rating) {
  console.log('vue on submit', rating);
});
<script src="https://vuejs.org/js/vue.min.js"></script>
<div id="rating-edit-container">
  <rating-edit :rating="rating"></rating-edit>
</div>

In an older front-end code, I aim to incorporate a Vue-based modular form and retrieve the data when submitted.

This is the component's code. Please take note of the submit function triggering this.$emit('submit', rating);

let result = {
  props:['rating'],
  methods: {
    submit: function submit () {
      let rating = this.rating;
      this.$emit('submit', rating);
      console.log('submit triggered');
    }
  }
};

export default result;

And now in the old code, I am listening for the events:

import Vue from 'vue';
import ratingEditVue from './rating-edit.vue';


Vue.component('rating-edit', ratingEditVue);

const aRating = {
  title: 'title',
  remark: 'remark'
};

let vueApp = new Vue({
  el: '#rating-edit-container',
  data: {
    rating: aRating
  }
});

vueApp.$on('submit', function(rating) {
  console.log('vue on submit', rating);
});

Based on my understanding of Vue events, this setup should function correctly. However, $on('submit', handlerFunction) never seems to be invoked.

Addendum:

I've made adjustments to the example. Apologies for not doing so initially.

Answer №1

The issue arises from emitting within the same scope depth of your rating-edit component.

To solve this, emit to the parent using this.$parent.$emit so that the event can be received by the parent component. If you find yourself needing to do this in multiple locations or at various depths, consider utilizing an event bus instead.

Vue.component('rating-edit', {
    template:`
    <form>
      <input v-model="rating.title" type="text">
      <textarea v-model="rating.remark">{{rating.remark}}</textarea>
      <button type="button"
        @click="submit">
        Save
      </button>
    </form>`,
    props:['rating'],
    methods: {
      submit: function submit () {
        let rating = this.rating;
        this.$parent.$emit('submit', rating);
        console.log('submit was emitted');
      }
    }
  });

const aRating = {
    title: 'title',
    remark: 'remark'
  };

let vueApp = new Vue({
    el: '#rating-edit-container',
    data: {
      rating: aRating
    }
  });

vueApp.$on('submit', function(rating) {
  console.log('vue on submit', rating);
});
<script src="https://vuejs.org/js/vue.min.js"></script>
<div id="rating-edit-container">
  <rating-edit :rating="rating"></rating-edit>
</div>

Answer №2

vueApp.$on('submit', function(rating) {
  console.log('vue on submit', rating);
});

The code snippet above listens for the 'submit' event emitted by 'vueApp'. However, please note that this handler will only respond to direct emissions of 'submit' events from 'vueApp' using 'vueApp.$emit('submit')'.

It's important to remember that Vue events do not bubble up through nested components.

If your template structure includes a component like '#rating-edit-container', it should look similar to the following:

<template id="rating-edit-container">
  <div>
    <rating-edit @submit="onRatingSubmit"></rating-edit>
  </div>
</template>

To handle the 'submit' event within your component, you need to declare a method such as 'onRatingSubmit' in the methods section of your Vue instance:

let vueApp = new Vue({
  el: '#rating-edit-container',
  methods: {
    onRatingSubmit(rating) {
      console.log('rating submit', rating);
    },
  },
});

EDIT

In continuation with the issue previously mentioned, I made some modifications to the provided code snippet. The changes include eliminating emission on '$parent' and focusing on 'this', as well as registering the event listener directly on the 'rating-edit' element within the template.

Please see the updated code snippet below:

Vue.component('rating-edit', {
    template: `
    <form>
      <input v-model="rating.title" type="text">
      <textarea v-model="rating.remark">{{rating.remark}}</textarea>
      <button type="button"
        @click="submit">
        Save
      </button>
    </form>`,
    props:['rating'],
    methods: {
      submit: function submit () {
        let rating = this.rating;
        this.$emit('submit', rating);
        console.log('submit was emitted');
      }
    }
 });

const aRating = {
    title: 'title',
    remark: 'remark'
 };

let vueApp = new Vue({
    el: '#rating-edit-container',
    data: {
      rating: aRating
    },
    methods: {
      onSubmit(rating) {
        console.log('vue on submit', rating);
      },
    },
});
Please ensure that the necessary scripts are included in the appropriate sections.

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

Issue with child routes not functioning properly within single spa React application

{ "name": "@my-react-app/demo", "scripts": { "start": "webpack serve", "start:standalone": "webpack serve --env standalone", "build": "concurrently npm:build:*", "build:webpack": "webpack --mode=production", "analyze": "webpack --mo ...

concealing the upper header while scrolling and shifting the primary header upwards

Is there a way to use CSS to move the main header navigation, including the logo and links, on my website up when scrolling down in order to hide the top black bar header that contains contact information? The website in question is atm.truenorthmediasol ...

The execution of the return statement in the catch block is unsuccessful

Here is a simple example that results in an error because the variable tl was not specified: function allmatches() { SpreadsheetApp.getActive().getSheetByName('data').getRange('A1').setValue(tl) } To track any errors that occur durin ...

Alter the background color of a div contingent on the checkbox being checked within

I am in search of a solution to modify the background color of a parent div that contains a checkbox. The condition is that the background color should only change when the 'checked' attribute is present within the tag. HTML <div class="comp ...

What is the best way to create a feature in Vue that filters options in real-time as we type into a

In my Vue application, I am trying to implement dynamic filtering for the options in a search box as the user types. Currently, the search box displays the entire list of options without any filtering happening even when the user is typing. <el-form-it ...

Using Javascript to retrieve information from a json file

I am currently working on incorporating JSON data into my script. I have noticed that when I manually declare a variable and check the console output, everything seems to work fine. <script> data = '[{"id": 1,"name": "Germany"},{"id": 2,"name": ...

Update the color of the div when all checkboxes in the hidden form are selected

Seeking help for multiple issues I'm facing with my code. Here is the link to the code. HTML for Upper Table: <div class="block"> <table> <tr> <th>Nr.</th> <th style="width: 200px">Task</th& ...

Looking to convert a jQuery function to plain JavaScript code?

Struggling with my homework, I must apologize for any mistakes in my English. My task involves creating a chat using node.js and I found some code snippets on a website "" which I used successfully. The issue now is that the chat relies on old jQuery libr ...

There seems to be an issue with loading data for the grid from the JSON

I need some help with creating a fiddle that loads data from a json file. I'm not sure why the data is not loading properly. You can view my fiddle here: Fiddle This is my code for the data store: Ext.create('Ext.data.Store', { storeI ...

I am confused about the process of mounting components

Utilizing pattern container/representational components, I have a CardContainer component that retrieves data from a server and passes it to a Card component. Container Component: class CardContainer extends Component { state = { 'ca ...

Update the Vue component upon fetching new data

How can I continuously refresh the list of items when a button in a sibling component is clicked? The watch method only triggers once, but I need it to constantly refresh. This is the parent element: <template> <div class="container"& ...

What is the best way to integrate Vuex State data into methods?

Reviewing the code snippet below: <template> <div :id="svgId" class="svg-container"></div> </template> <script> import { mapState } from 'vuex' export default { name: 'Space', data: function() { ...

Approach to dividing PHP output into multiple outputs (AJAX, PHP) (nested AJAX requests, AJAX inside AJAX loop?)

Seeking advice on how to efficiently handle PHP output in small chunks for AJAX responseText. The project involves a webpage using AJAX to input a last name, which is then processed by a PHP program. The PHP code randomly selects three people with differen ...

Applying scoped styling in Vue.js renders the SCSS ineffective

My SCSS code works perfectly on a simple page where I apply background-color. However, when I make the file scoped, the SCSS doesn't seem to have any effect. It's important for me to keep this component scoped so that the background-color doesn&a ...

The jQuery toggle function seems to be skipping alternate items

I have recently started learning Javascript and JQuery. Currently, I am working on creating a comment system where you can click reply to display the form. However, I'm facing an issue where the form only shows up for the first comment reply, not for ...

Storing complex data structures in Firebase using VUEX

I am struggling to properly store my 'players' data within my team data structure. Currently, it is being saved with the team id but I need it to be nested inside of teams. Essentially, I want the players to seamlessly integrate and be appended ...

Utilizing the Google Maps API to geocode addresses and postponing the retrieval of the data

Utilizing Google's maps API to geocode two addresses has brought about a unique challenge for me. I am deferring the returned results and utilizing a $.when().then() method to execute my logic once I receive the coordinates for the string addresses. T ...

How can Angular's as-syntax be used to access the selected object?

When using syntax like ng-options="p.id as p.name for p in options" to select options, I encounter an issue. I require access to the variable p as well. This is necessary for displaying additional labels near inputs or buttons, or even making changes to in ...

What is the best way to identify when a cell has been modified in ng-grid aside from just relying on the ng-grid event

My web application features an editable ng-grid that has greatly simplified my work, but I have encountered a minor issue. I need a way to detect when a user makes changes to the grid without having to compare each field before and after. Currently, I am ...

Do not use Express.js to serve the index.html file

Encountered an issue when attempting to run my Express.js solution. Instead of opening my desired index.html file located in the client directory, it kept opening the index.jade file from the views folder with the message "Welcome to Express" on the browse ...