0

I have two separate Vue components that need to talk to each other via an eventbus. Like:

form-component.Vue

import events from './events'
export default {
   ...
   methods() {
     sumbitForm() {
       events.$emit('form-submitted', data)
     }
   }
   ...
}

other-component.Vue

import events from './events'
export default {
  ....
  mounted() {
    events.$on('form-submitted, data => {
      this.list.push(data);
    }
  },
  data() {
    return {
      list: []
    }
  }
  ....
}

But when the event is listened to 'this' is not referring to 'other-component' but to the actual eventbus 'events'.

How would I go about this problem?

2
  • Your syntax here has mismatched { Commented Apr 11, 2018 at 12:05
  • Sorry, this is just some simplified code I made up to make the problem more focussed. Editing code in the stackoverflow textbox isn't pretty haha Commented Apr 11, 2018 at 12:14

2 Answers 2

2

It sounds to me like you're misreading the problem. An arrow function binds its context, and the context of that arrow function is correctly bound to the other-component because it is within a method, and methods are auto-bound to their components. The below example works as expected.

const events = new Vue();

Vue.component('formComponent', {
  template: '<button @click="submitForm">Submit</button>',
  methods: {
    submitForm() {
      events.$emit('form-submitted', {
        foo: 1
      });
    }
  }
});

Vue.component('otherComponent', {
  template: '<div><div v-for="item in list">{{item}}</div></div>',
  data() {
    return {
      list: []
    }
  },
  mounted() {
    events.$on('form-submitted', data => {
      this.list.push(data);
    });
  }
});

new Vue({
  el: '#app'
});
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<div id="app">
  <form-component></form-component>
  <other-component></other-component>
</div>

Sign up to request clarification or add additional context in comments.

1 Comment

This worked. The problem was that I have an http request after it, wich overrides the array. For some reason if I place it above the event listener it doesnt mess up things.. weird.
0

One solution would be to copy your this in a variable outside and use that to access the component's data properties. For example, this should work:

import events from './events'
export default {
  ....
  mounted() {
    var that = this;
    events.$on('form-submitted, function(data) {
      that.list.push(data);
    )
  },
  data() {
    return {
      list: []
    }
  }
  ....
}

4 Comments

Just tried this, but still doesnt seem to recognize 'list' as an array. I get ''TypeError: list.push is not a function''.
When i do something like "that.list = []; that.list.push(data);" it does work, but obviously it overrides any data that i might have had in the array in the first place
Updated the answer, please don't use arrow functions as arrow function binds this to parent context.
Arrow functions are fine inside methods. You don't want to use them to define methods or lifecycle hooks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.