Dennis Betman
Dennis Betman

Reputation: 330

Let 2 single file components communicate with each other

How can I let 2 single file components communicate with each other.

For example: I have 2 file components. Content.vue and a Aside.vue

How can i create something like, when I click on a button inside Aside.vue that something will update inside Content.vue

this is how the 2 single file compontents look inside the index.html:

  <div class="container articleContainer">
    <article-content></article-content>
    <article-aside></article-aside>
  </div>

Aside.vue:

<template>
  <aside>
    <span @click="updateCounter">Dit is een aside.</span>
  </aside>
</template>

<script>
  export default {
    data() {
      return {
        aside: "aside message"
      }
    }
  }
</script>

Content.vue

<template>
  <article>
    <p>{{ counter }}</p>
    <button @click="updateCounter">Update Counter</button>
  </article>
</template>

<script>    
  export default {
    data() {
      return {
        counter: 0
      }
    }
    methods: {
      updateCounter: function() {
        this.counter = this.counter + 2;
      },
    }
  }
</script>

When I click on the span inside the Aside template how can I use updateCounter to update the counter inside Content.vue.

Upvotes: 2

Views: 201

Answers (3)

Vamsi Krishna
Vamsi Krishna

Reputation: 31352

if your app is not aas big or complex to use vuex , you can set up an EventBus like this:

export const EventBus = new Vue();// in your main.js file

in Aside.vue:

<template>
  <aside>
    <span @click="updateCounter">Dit is een aside.</span>
  </aside>
</template>

<script>
import {EventBus} from './path/to/main.js'
  export default {
    data() {
      return {
        aside: "aside message"
      }
    },
    methods:{
        updateCounter(){
            EventBus.emit('updateCounter');
        }
    }
  }
</script> 

in Content.vue

<template>
  <article>
    <p>{{ counter }}</p>
    <button @click="updateCounter">Update Counter</button>
  </article>
</template>

<script>  
  import {EventBus} from './path/to/main.js'
  export default {
    data() {
      return {
        counter: 0
      }
    }
    created() {
        
        EventBus.on('updateCounter', () => {
            this.counter = this.counter + 2;
        });
    },
    methods: {
        updateCounter: function() {
            this.counter = this.counter + 2;
        },
    }
  }
</script> 

Upvotes: 1

Jekis
Jekis

Reputation: 4695

Communication between any components using Event Bus

Event Bus is not limited to a parent-child relation. You can share information between any components.

<script>
export default
    name: 'ComponentA',
    methods: {
        sendGlobalMessage() {
            this.$root.$emit('message_from_a', arg1, arg2);
        }
    }
}
</script>

In the above ComponentA, we are firing an event “message_from_a” and passing arguments. Arguments are optional here. Any other component can listen to this event.

<script>
export default
    name: 'ComponentB',
    mounted() {
        this.$root.$on('message_from_a', (arg1, arg2) => {
            console.log('Message received');
        });
    }
}
</script>

In ComponentB to listen an event, we have to register it first. We can do so by putting an event listener inside mounted() callback. This callback will be triggered when an event is fired from any component.

source

Upvotes: 0

sandrooco
sandrooco

Reputation: 8756

Option 1: Have a value in the App.vue that gets reflected by both the components. (That's the this.$parent.someParentMethod(someValue);-way, which would be mixed with props).

Option 2 (way easier, cleaner and best-practice): vuex

Upvotes: 1

Related Questions