VueJS: Passing Data to Parent Components

VueJS: Passing Data to Parent Components

Building modern frontend applications is all about data manipulation, you will mostly be dealing with user interaction with data present in your app and based on domain logic modifying the state of data and finally syncing it your backend data store.
We will be covering 3 very basic methods to change the state of data in vue app.

  • Root components
  • Custom Events
  • Global Event Bus


Root components


This is the most primitive way to both store and modify the data with vue application we can get started with a simple scenario.
If you have defined your root component as following

new Vue({
 data: {
   todo: []
 },
 methods: {
   addTodo: function () { /* ... */ },
   updateTodo: function () { /* ... */ },
   removeTodo: function () { /* ... */ },
   getTodo: function () { /* ... */ }
 }
})



You can now very easily refer to root component within child components and modify state directly as follows.

// Get root data
this.$root.todo

// Set root data
this.$root.todo = null

// Call root methods
this.$root.addTodo(todo)


As mentioned above this is most simple way to have a single source of truth within your app but it is generally not recommended and usually frowned up despite of simplicity you are ignoring a very basic best practice to keep your components reusable and contained moreover debugging and testing will be a nightmare and if you plan to add more features things will get quickly out of hands and it will not be manageable.

Custom Events


This is most natural of passing state changes back to parent component as we all know vue has adapted one way data flow and for good reasons so in everyday routine you will refactor your components based on single responsibility principle you break the orignal components to various child components.Now they need data you pass the data to them using props but remember we are in realm of one way data flow so suppose now user has interacted with that child component and now you need to communicate that change back to parent what would you do answer is custom events.
Let's say we have structured our todo app like this after refactoring.


<todo-app
 ...
 <todo-editor v:bind:current-selection />
<todo-item>
<todo-item>
<todo-item>
<todo-item>
></todo-app>

We have a todo app containing the todo app editor which takes the current selection the end user is editing as a prop now what happen when user is finished with changing the state, its need be communicated back to its parent components.

<button v-on:click="$emit('update-item', todo)"> Update Item </button>

Within editor we can emit an event “update-item” with the current todo item being passed as a second param.


Now back in parent component we can listen to the update event and get the updated todo item as well.

 <todo-editor v:bind:current-selection v-on:update-item=”onUpdateItem” />

Global Event Bus


So first of all do you know vuejs comes with a dedicated event bus, how cool is that. As we are currently covering passing data back to parent components it’s important to mention that within event bus you can listen to state changes within any part of your frontend application whether the component is directly up in hierarchy or it its further down by using eventbus it doesn't matter. Usually this technique is used to propagate changes to unrelated components within your app.
We first start by initializing event bus within our app.

import Vue from 'vue';
export const EventBus = new Vue();

It's quite simple simple, Yes.

Now in order to generate events and send them to event bus you will have to import EventBus and use $emit method to do so, this is explained in detail in the following example.

<template>
  <button class="btn btn-primary" @click="updateTodoItem()"></div>
</template>

<script>
// Import the EventBus we just created.
import { EventBus } from './event-bus.js';

export default {
  props: ["currentTodoItem"],
  data(): function(){
      return {
          todoItem: Object.assign({}, this.currentTodoITem)
      }
  }
  methods: {
    updateTodoItem() {
    
      EventBus.$emit('update-item', this.todoItem);
    }
  }
}
</script>

Now in order to listen to events you can simply import event bus again and use $on method to listen.


// Import the EventBus.
import { EventBus } from './event-bus.js';

// Listen for update-todo event 
EventBus.$on('update-todo', todoItem => {
  console.log(`Todo item is updated `)
});

You will usually be listening to these components within other components its recommended to stop listening once your component is destroyed, You can use $off method of event store inside before destroy hook of your component.