I am attempting to rebuild Vuex's Getting Started example by utilizing multiple components, yet I am struggling to understand how to call root methods from within these components

The project I'm working on can be found here. It is a simple one, but for the purpose of learning, I divided it into index and four js files (parent, child, root, and store). My challenge lies in figuring out how to call the increment and decrement root methods in the child component without resorting to commits within the elements or engaging in poor practices like using props or this.$root inside the components.

Here is the code breakdown:

index.html:

<div id="app">
        <parent></parent>
</div>

root.js:

let vm = new Vue({
    el: '#app',
    store,
    methods:{
        increment(){
            store.commit('incrementar')
        },
        decrement(){
            store.commit('decrementar')
        } 
    }
})

store.js:

const store = new Vuex.Store({
    state:{
        numero: 11
    },
    mutations:{
        incrementar(state){
            state.numero++
        },
        decrementar(state){
            state.numero--
        }
    }
})

parent.js:

Vue.component('parent',{
    template:
    `
    <div>
        <h1>Number: {{$store.state.number}}</h1>
        <child></child>
    </div>
    `
})

child.js:

Vue.component('child',{
    template:
    `
    <div>
        <button @click="increment">+</button>
        <button @click="decrement">-</button>
        <h1>Number: {{number}}</h1>
    </div>
    `,
    computed: {
        number() {
            return store.state.number
        }
      }

I have read that events should be used, but I am unsure about implementing them with the buttons. Keep in mind that I am relatively new to JavaScript, Vue, and Vuex.

Answer №1

If you want to utilize instance methods events, refer to the documentation here. An example code snippet is provided below:

root.js:

let vm = new Vue({
    el: '#app',
    store,
  mounted () {
    let self = this
    self.$root.$on('FancyEventName', self.HandleFancyEvent)
  },
  beforeDestroy () {
    let self = this
    self.$root.$off('FancyEventName', self.HandleFancyEvent)
  },
  methods: {
    HandleFancyEvent (arg) {
      let self = this
      if(arg === true){
       self.increment()
     } else{
       self.decrement()
     }
    },
    methods:{
        increment(){
            store.commit('incrementar')
        },
        decrement(){
            store.commit('decrementar')
        } 
    }
})

child.js:

Vue.component('child',{
    template:
    `
    <div>
        <button @click="increment">+</button>
        <button @click="decrement">-</button>
        <h1>Numero: {{numero}}</h1>
    </div>
    `,
    methods:{
        increment(){
            let self = this
            self.$root.$emit('FancyEventName', true)
        },
        decrement(){
            let self = this
            self.$root.$emit('FancyEventName', false)
        } 
    }
    computed: {
        numero() {
            return store.state.numero
        }
      }

This setup will function effectively. Additionally, an alternate approach involves creating a separate event bus for communication:

// event-bus.js
import Vue from 'vue';
const EventBus = new Vue();
export default EventBus;

Here is how you can use the Event Bus in components:

// component-a.js
import Vue from 'vue';
import EventBus from './event-bus';
Vue.component('component-a', {
  ...
  methods: {
    emitMethod () {
       EventBus.$emit('EVENT_NAME', payLoad);
    }
  }
});

And a second component which reacts to this event:

// component-b.js
import Vue from 'vue';
import EventBus from './event-bus';
Vue.component(‘component-b’, {
  ...
  mounted () {
    EventBus.$on(‘EVENT_NAME’, function (payLoad) {
      ...
    });
  }
});

Both methods achieve the same result, with the only distinction being the utilization of a separate instance for communication purposes.

I hope this explanation proves helpful! 🙂

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

What is causing the datepicker to return null value?

Having a dilemma with two textboxes named start_date and end_date. Every time I click the search button, it appears to return a null value. I am trying to find a way to alert and display the value inside these textboxes. It seems like the issue arises wh ...

Is there a way to modify the color scheme of the hamburger icon

I'm experiencing difficulties changing the color of a hamburger icon. I've searched for the specific code responsible for the color change, but I haven't been able to locate it. Ideally, I want the color to be white, but on small screens, i ...

The ajax response is returning the entire page's html code instead of just the text content from the editor

I've been working with CKEditor and I'm using AJAX to send the editor's content via POST method. However, when I try to display the response in a div, the HTML for the entire page is being returned instead of just the editor's content. ...

A variable must be defined within a specific block in order to be recognized

In an effort to enhance my code within a passport function, I am looking to pull values from a mongodb Database rather than from an array. The initial functioning code appeared as follows: passport.use( new LocalStrategy( { usernameField: ...

How can I create a hover effect animation in React?

I am looking to replicate the menu item underline animation demonstrated in this example. In jQuery, I would easily achieve this by obtaining the left position and width of a menu item, then using stop.animation on hover. Attempting this animation with R ...

Monitoring Object Changes in Angular 4

ETA: I am aware of different methods for monitoring my form for alterations. However, that is not the focus of my inquiry. As indicated by the title, my question pertains to observing changes within an object. The application displayed below is solely for ...

Background image of HTML Iframe element does not display - Inline style block

https://i.stack.imgur.com/JW26M.png After setting the iframe's innerHTML using this line of code: iframedoc.body.innerHTML = tinyMCE.activeEditor.getContent(); The styles for the elements within the iframe are contained in an inline style block. Ho ...

Exploring Tmbd Movie Database with React.js - Results of searches will only display after the application is recompiled

Presented here is my component. The challenge I am facing pertains to the fact that upon entering a search query, no results are displayed until I manually save in the code editor and trigger a recompilation of the application. Is there a more efficient ap ...

Project in Three.js where the camera remains focused on the object while in a top-down perspective

I am currently working on developing a top-down game using Three.js, inspired by classic arcade games like Frogger. I am facing challenges in ensuring that the camera stays centered on the main character as it moves across the screen. I am currently util ...

Angular Error TS2339: The property 'car' is missing from type 'Array of Vehicles'

Encountering Angular Error TS2339: Property 'vehicle' is not found on type 'Vehicle[]'. The error is occurring on data.vehicle.results. Any thoughts on what could be causing this issue? Is the problem related to the Vehicle model? I hav ...

Populating options in <select> for Internet Explorer version 5

Let me address the first question here. The reason why I am using IE5 is because I am working on a Windows CE device which limits me to this browser. My application involves a webpage with various elements. In my HTML code, I have two text fields and a se ...

I'm having trouble importing sqlite3 and knex-js into my Electron React application

Whenever I try to import sqlite3 to test my database connection, I encounter an error. Upon inspecting the development tools, I came across the following error message: Uncaught ReferenceError: require is not defined at Object.path (external "path ...

Troubleshooting a Problem with AngularJS $.ajax

Oops! Looks like there's an issue with the XMLHttpRequest. The URL is returning a preflight error with HTTP status code 404. I encountered this error message. Any thoughts on how to resolve it? var settings = { "async": true, "crossDomain": ...

The function cannot be applied to d[h] due to a TypeError

Having some trouble with my code here. I'm trying to set up routes to display a gif using CSS animation when the page is loading. The gif shows up initially, but then everything fades out and the gif remains on the page. Additionally, I'm getting ...

What is the proper way to incorporate the "pdf" package into a TypeScript project?

I recently installed pdf and its types using the following command: npm install --save pdf @types/pdf However, I am struggling to find any documentation on how to actually use this package. When I try the following code: import {PDFJS} from 'pdf&ap ...

Leveraging various routes to access data with a shared VueJS 3 component

Could you please review this code snippet: It displays two routes that utilize the same component to fetch content from an API. Main.js const router = createRouter({ history: createWebHistory(), routes: [ { path: "/route1& ...

Unable to retrieve information from req.body, however able to retrieve data from req.params

I'm facing an issue with my code where I am not able to retrieve user data from req.body as it returns undefined. However, I can successfully access the required information from req.params. Can anyone provide guidance on how to resolve this issue? co ...

Ways to display the ChaptersButton in Videojs-Player

I'm trying to incorporate videojs (version 8.10.0) into my project and provide viewers with a way to select chapters within the video. According to the official documentation, it seems that simply including a track element linking to a VTT file within ...

How to create a vertically scrollable div within another div by utilizing scrollTop in jQuery

I need assistance with scrolling the #container div inside the .bloc_1_medias div. The height of #container is greater than that of .bloc_1_medias. My goal is to implement a function where clicking on the "next" and "previous" text will scroll the #contai ...

Creating a custom Higher Order Component to seamlessly connect react-relay and react-router using TypeScript

Hey there! So, my Frankenstein monster project has decided to go rogue and I'm running out of hair to pull out. Any help would be greatly appreciated. I've been working on setting up a simple app with React, React-Router, React-Relay, and Typesc ...