Can you explain the distinction between Vue's 'v-on' directive and vue.$on method?

If I have two sibling components set up like this:

<div id="root2">
    <some-component>First</some-component>
    <some-component>Second</some-component>
</div>

... and these components are coded as follows:

Vue.component('some-component', {
    template: '<button @click="doSomething" @somethingwasdone="this.reactToSomething" :disabled="this.isDisabled"><slot /></button>',
    methods: {
        doSomething() {
            Event.$emit('somethingWasDone');
        },

        reactToSomething() {
            this.isDisabled = true;
        }
    },
    data() {
        return {
            isDisabled: false,
        }
    },
    created() {
        Event.$on('somethingWasDone', () => this.reactToSomething());
    }
});

If my goal is to disable both buttons when one of them is clicked, I have implemented two event listeners intentionally - one using a 'v-on' directive and the other with the $on method in Vue instance. However, I am experiencing difficulty getting the former to function correctly without understanding the reason behind it.

I suspect that the issue may be related to the scope of the emitted event. Despite using the v-on directive, even the component emitting the event does not respond to it. Any assistance in resolving this matter would be highly valued!

Thank you,

Ryan


Update: Upon reviewing my code, I identified an error where the v-on directive was listening for 'componentclicked' instead of 'somethingwasdone'. After correcting this mistake, I confirmed that both approaches indeed work effectively.

Answer №1

Each Vue component instance, including the root one, is equipped with $on and $emit methods for emitting and receiving events. It's important to consider the scope of the emitted event when working with events.

In the provided example, it appears that you are attempting to emit and catch an event within the same component. In such cases, you should utilize the component instance $emit and $on methods to ensure the event remains within that scope. The syntax for this involves using this.$emit() and this.$on(), where this refers to the component instance.

Vue.component('some-component', {
    template: '<button @click="doSomething" @somethingWasDone="this.reactToSomething" :disabled="this.isDisabled"><slot /></button>',
    methods: {
        doSomething() {
            this.$emit('somethingWasDone');
        },

        reactToSomething() {
            this.isDisabled = true;
        }
    },
    data() {
        return {
            isDisabled: false,
        }
    },
    created() {
        this.$on('somethingWasDone', () => this.reactToSomething());
    }
});

The v-on syntax in the template is used to listen to the same event from the parent component.

<div id="root2">
     <some-component v-on:somethingWasDone="doSomething">First</some-component>
    <some-component v-on:somethingWasDone="doSomething">Second</some-component>
</div>

If you opt to use Vue.$on and Vue.$emit on the root instance, you will be emitting/listening to events at a global level.

Answer №2

From my understanding, event emissions are directed towards the parent component, requiring logic implementation in the parent component.

<div id="root2">
  <some-component
    v-on:somethingWasDone="isDisabled = true"
    :disabled="isDisabled">
   First
  </some-component>

  <some-component
    v-on:somethingWasDone="isDisabled = true"
    :isDisabled="isDisabled">
   Second
  </some-component>
</div>

// ...

data() {
  return {
    isDisabled: false
  }
}

Add the isDisabled variable to the parent and also as a prop in some-component.

Vue.component('some-component', {
    template: '<button @click="doSomething" @componentclicked="this.reactToSomething" :disabled="this.isDisabled"><slot /></button>',
    props: ["isDisabled"],
    methods: {
        doSomething() {
            Event.$emit('somethingWasDone');
        }
    },
});

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

The submission of the form with the ID "myForm" using document.getElementById("myForm").submit() is

<form name="formName" id="formName" action="" method="post" autocomplete="off"> <input type="hidden" name="text1" id="text1" value='0' /> <input type="button" name ="submit" onClick="Submit()" value="submit"> ...

Step-by-step guide on retrieving the button text by utilizing a method call

Currently, I am troubleshooting a demo and I'm puzzled as to why the text of the #add-point button is not displaying. $("#add-point").on("click", function(){ activatePointTool(); }); function activatePointTool() { var tool = $(this).text().toU ...

Tips for creating a console.log wrapper specifically designed for Angular2 using Typescript

Is there a way to create a custom global logging function in Angular 2 TypeScript project that can be used instead of console.log for services and components? I envision the function looking like this: mylogger.ts function mylogger(msg){ console.log ...

Step-by-step guide on using nodemon on a web hosting server

I am currently designing a website that includes a login form and I am in the process of uploading it to a web hosting service In order to activate my login form, I have to use node index Is there a way to change the destination of this tag: <li class ...

How can I reverse the names displayed in ng-repeat when I click?

When utilizing the orderby filter in angularjs, I want to be able to sort the data only when the button is clicked. If the button is not clicked, the sorting order should not be displayed. <tr ng-repeat="tools in toolsfilter | orderBy:orderByField:reve ...

Providing a user with a special discount tailored to their email address?

<script type="text/javascript"> function updatePrice() { var price = document.getElementById("product").value; var size_price = document.getElementById("size").value; var a=parseInt(price);//parsed type price var b=parseInt(size_price);//pa ...

Using SVG files as properties in React from a data.js file

I have a website where I store my content in a data.js file and pass it to my components using props. Everything is working correctly, except for my .svg files. When I try to display them, they do not appear. However, if I change the extension of the image ...

Is there any method to avoid the hassle of constantly adjusting margins and paddings on my one-page website?

One issue I encountered was that the buttons weren't scrolling me to the top of the anchor, instead scrolling too far into the section due to the fixed navbar overlapping. I tried solving it with margins and paddings but believe there must be a simpl ...

Is there a way to control the quantity of items being displayed in my ng-repeat directive?

Here are the objects in my array: 01-543BY: Array[1] 03-45BD23: Array[1] 03-67BS50: Array[1] 06-78FR90: Array[1] 07-467BY3: Array[1] 09-23DF76: Array[1] Currently, I have a total of six objects, but I only want to display four. This is how I am using ng- ...

Angular Unit Testing: Executing Multiple expectGET's within a Singular Test

I am facing an issue with a unit test that fails to read the JSON in the second request properly This is my implementation of the Config factory (function() { 'use strict'; angular.module('commercial.factories').factory(&apos ...

JavaScript - Retrieve events from an element and assign them to a keyboard button

I am currently curious about the following scenario: Suppose I have an element with a particular event. For example, when this element is clicked, it triggers alert('clicked); Now, my question is: Is there a way to capture the events of this element ...

Sorting a Javascript table performs effectively, however, the results may vary when iterating through all the indexes

I'm currently using a function to sort a table I have: function ReorderSupplyGP(table){ table.find('tr:not(.kn-table_summary)').sort(function (a, b) { var tda = $(a).find('td:eq(1)').text().trim(); var tdb = $(b).find(&a ...

Device sending incorrect JSON format

A JSON response from a device is as follows: { "Order": ""3"", "ID": ""SHEET"", "Name": ""Time Sheet"", "ConID": ""!s?d2SzxcSDW1cf$*@4812sC#"" } The property values in the JSON are enclosed in double quotes, causing them to be incorrect. Is ...

Implementing a 'Load More' button for a list in Vue.js

I am currently working on adding a load more button to my code. While I could achieve this using JavaScript, I am facing difficulties implementing it in Vue.js. Here is the Vue code I have been working with. I attempted to target the element with the compa ...

Generate with different HTML elements

This is a simple React code snippet: var Greetings = React.createClass({ render: function() { return <div>Greetings {this.props.name}</div>; } }); ReactDOM.render( <Greetings name="World" />, document.getElementB ...

What could be causing my array to be undefined upon the creation of a Vue component?

I'm struggling to comprehend why my array is showing as undefined in my Vue component. The issue arises in the following scenario: The SelectCategories.vue component uses the router to navigate to the Quiz.vue component. Here, I utilize props to tran ...

Retrieving information from an external API in response to an express GET request

After reviewing the sample code in the gtfs-realtime-bindings library's documentation, I attempted to implement a similar logic within my router. However, I encountered issues with extracting the result from the request() route.get('/', (req ...

Tips for transferring a function from a Node.js server to a client

Hey everyone, I'm trying to achieve the following: On the Node server side: var fn = function(){ alert("hello"); } I am looking for a way to send this function to the client side. I am currently using AngularJS, but I am open to other solution ...

Transferring the value of my PHP variable to a JavaScript file

Hello everyone, <script src="../../record/recordmp3.js?id=<?php echo $_GET['id'];?>&&test_no=<?php echo $_GET['test_no'];?>"></script> <script type="text/javascript" data-my_var_1="some_val_1" data-m ...

Prevent Click Event on Angular Mat-Button

One of the challenges I'm facing involves a column with buttons within a mat-table. These buttons need to be enabled or disabled based on a value, which is working as intended. However, a new issue arises when a user clicks on a disabled button, resul ...