spratap124
spratap124

Reputation: 171

how to update child component's property using props in vue js?

I have a addToCart component(child) on foodList component(parent). and there is another component Cart. i want to reset the addToCart component's counter value to 0 whenever i will empty my cart.

App.vue

data() {
  return {
    msg: "Welcome to Your Food Ordering App",
    foodData:[],
    cart:[],
    reset:false
 };
},
methods: {
  emptyCart:function(){
    this.reset = true;
    this.cart = [];
  }
}

foodList.vue

export default {
  props:['foods','reset'],
  data() {
    return {

    };
  }
}

<addToCart :reset="reset"></addToCart>

addToCart

export default {
  props:['food','reset'],
  data(){
    return {
      counter:0
    }
  },
  beforeMount() {
    if(this.reset) {
      this.counter = 0;
    }
  }

in app.vue I'm modifying the reset property to "true" and then passing it to foodList.vue, then passing it to addToCart.vue.

In addToCart.vue I'm checking if reset prop is true then set the counter to 0;

But this is not working.let me know where am I missing?

Please refer to this link for complete code.

food ordering app

Upvotes: 3

Views: 9295

Answers (1)

Orlandster
Orlandster

Reputation: 4858

So basically you want to pass the state over multiple components. There are multiple ways to achieve this. These are my three recommend ones.

Centralized State management

In order to handle states easier, you can make use of a centralized state management tool like vuex: https://github.com/vuejs/vuex

This is what I recommend you, especially when it comes to bigger applications, where you need to pass the state over multiple levels of components. Trust me, this makes your life a lot easier.

Property binding

The most basic way to communicate with your child components is property binding. But especially when it comes to multi-level communication it can get quite messy.

In this case, you would simply add counter to both of your child components props array like this:

foodList.vue (1. Level Child Component)

export default {
  props:['foods','reset', 'counter'],
  // ... your stuff
}

And include the component like this:

<foodList :counter="counter"></foodList>

addToCart.vue (2. Level Child Component)

export default {
  props:['food','reset', 'counter'],
  // ... your stuff
}

And finally include the component like this:

<addToCart :reset="reset" :counter="counter"></addToCart>

As a last step, you can specify counter in the data object of your root component and then modify it on a certain event. The state will be passed down.

App.vue

data() {
  return {
    // ... your stuff
    counter: 0,
 };
},
methods: {
  emptyCart:function(){
    // ... your stuff
    this.counter = 0; // reset the counter from your parent component
  }
}

Event Bus

As a third option, you could make use of Vue's event bus. This is the option I personally choose for applications, which get too messy with simple property binding, but still are kind of too small to make us of Centralized State management.

To get started create a file called event-bus.js and then add the following code to it:

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

Now you can simply trigger events from your parent Component like this:

App.vue

import { EventBus } from './event-bus.js'; // check the path
export default {
  // ... your stuff
  methods: {
    emptyCart:function(){
      // ... your stuff
      EventBus.$emit('counter-changed', 0); // trigger counter-changed event
    }
  }
}

And then listen to the counter-changed event in your child component.

addToCart.vue

import { EventBus } from './event-bus.js';
export default {
  // ... your stuff
  created() {
    EventBus.$on('counter-changed', newCounter => {
      this.counter = newCounter;
    });
  }
 }

Learn more about the event bus: https://alligator.io/vuejs/global-event-bus/

Upvotes: 7

Related Questions