Communication between Parent-Child Components in Vue Js

Component Communication

Today, we are going to learn how to communicate between components in Vue Js. To more understanding, We are going to play with a basic Shopping Bag example. The shopping bag will display the simple number of items. Our shopping bag will be going to use two events i.e. increment and decrement to adjust the number of items. Let’s jump to the codes without any delay.

Table of content

Parent to Child Communication

We can share the data from parent component to child through props option. Let’s say I want to send some value to the child component for the display. Assume we have a child component with the name ShopingBag. As the component name suggests, we display the total number of items to our shopping bag. It would be a very simple example. Take a look at the code for better understanding.

<template>
    <div>
        <h3>Products in Cart: {{ productInCart }}</h3>
    </div>
</template>
<script>
export default {
  name: "ShoppingBag",
  props: {
    productInCart: Number
  }
};
</script>

We have used the props option in our ShoppingBag to define the property and its type. It means our child component only receives the property assigned with the productInCart and the value should be a Number.

Let’s take a look at the codes to know how to use our ShoppingBag component.

<ShoppingBag productInCart="0" />

Child to Parent Communication

Now let’s add two buttons to add and delete the product (only numbers). Open the ShoppingBag component and add buttons to the template tag.

<template>
  <div class="hello">
    <h1>Products in Cart: {{ productInCart }}</h1>
    <button type="button">+</button>&nbsp;
    <button type="button">-</button>
  </div>
</template>

As you see at the codes that we have added the add (+) and delete (-) button without any event to our ShoppingBag child component. The event should be handled by the parent component. We need to use the $emit an event listener to communicate from child to parent component.

<template>
  <div class="hello">
    <h1>Products in Cart: {{ productInCart }}</h1>
    <button type="button" v-on:click="$emit('increment')">+</button>&nbsp;
    <button type="button" v-on:click="$emit('decrement')">-</button>
  </div>
</template>

As you can see at the codes that we have defined two events with the help of $emit and these events will get triggered on the click.

Now open the parent controller file from where we used the ShoppingBag component and add the event listener for the newly created events i.e. increment and decrement.

<template>
  <div id="app">
    <img width="25%" src="./assets/logo.png">
    <ShoppingBag 
      :productInCart="cart" 
      v-on:increment="cart += 1"
      v-on:decrement="cart -= 1"
      />
  </div>
</template>

It is a very basic example and we are only going to add or delete the numbers on a particular event. We have handled the cart through inline statement i.e.

v-on:increment="cart += 1"

If you feel messy with the inline statement, then you can handle it by defining the methods.

<template>
  <div id="app">
    <img width="25%" src="./assets/logo.png">
    <ShoppingBag
      :productInCart="cart"
      v-on:increment="handleIncrement"
      v-on:decrement="handleDecrement"
    />
  </div>
</template>

<script>
import ShoppingBag from "./components/ShoppingBag";

export default {
  name: "App",
  components: {
    ShoppingBag
  },
  data() {
    return {
      cart: 0
    };
  },
  methods: {
    handleIncrement() {
      this.cart += 1;
    },
    handleDecrement() {
      this.cart -= 1;
    }
  }
};
</script>