Valentine
Valentine

Reputation: 102

Vue JS 3: How to pass data from one component to another other?

I'm trying to share data stored in a variable favorite_count within the Favorites component in Favorites.vue file. I want to share that data with the App Component in the App.vue file but I'm not able to. I would want that if I change the value of favorite_count in the Favorites component, it changes in the App Component. Done quite some research on the web but no success yet. Any ideas on what I could be doing wrong?

Favorites.vue file

<template>
    <div class="row m-5">
        <h3 class="col-8">Your Favorites</h3>
        <div class="col-4">
            <p class="pull-right m-1">Picks 
            <span >{{ favorite_count }}</span>  / 5</p>
        </div>
        <hr>
    </div>
</template>
<script>
export default {
    name: 'favorites',
    data() {
        return {
            favorite_count: 5,
        }
    },
    methods: {
        changeFavoriteCount() { 
            this.favorite_count = this.favorite_count + 2;
        },
        emitToParent (event) {
          this.$emit('childToParent', this.favorite_count)
        }
    }
}
</script>

App.vue file

<template>
    <div class="navbar navbar-expand-md navbar-dark bg-primary">
        <div class="collapse navbar-collapse" id="navbarResponsive">
            <ul class="navbar-nav"> 
                <li class="nav-item">
                    <router-link to="/favorites" class="btn btn-info">
                      Favorites ( {{ favorite_count }} )
                    </router-link>
                </li>
            </ul>
        </div>
    </div> 
</template>
<script> 
import Favorites from './components/Favorites.vue'
 
export default {
  name: 'App',
  components: {
    Favorites
  },
  data () {
    return { 
      favorite_count: 0, 
    }
  }
}
</script>

Upvotes: 3

Views: 27303

Answers (2)

Cheetha
Cheetha

Reputation: 706

If you are going to use <router-view> later in your application, I would suggest this solution

If you were going to include Favorites inside <template> in App.vue, you can use props:

1. Declare your 'shared' variable in the parent component (App.vue)

data () {
  return { 
    favorite_count: 0, 
  }
},

2. Define props in your child component (Favorites.vue)

export default {
  props: { favorite_count: Number },
  ...
}

3. Pass favorite_count as prop to Favorites

<template>
  ...
    <Favorites :favorite_count="favorite_count" ... />
</template>

If you will need to update favorite_count - emit an event to parent component. More about it in Vue docs

Edit: Just to clarify: If you are going to update favorite_count from Favorites.vue, you need to emit an event to App.vue to avoid mutating props.

That also means you need to move your changeFavoriteCount() function to App.vue and apply a listener to your child component which will call this function:

// App.vue
<template>
  ...
    <Favorites 
       @your-update-event="changeFavoriteCount" 
       :favorite_count="favorite_count" ...
    />
</template>

...

changeFavoriteCount(newVal) { 
    this.favorite_count = newVal;
},

Upvotes: 9

sazzad
sazzad

Reputation: 525

change your Favourite.vue file like this

<template>
  <div class="row m-5">
    <h3 class="col-8">Your Favorites</h3>
    <div class="col-4">
      <p class="pull-right m-1">
        Picks <span>{{ favorite_count }}</span> / 5

        <button @click="changeFavoriteCount">Click me to change favorite_count</button>
      </p>
    </div>
    <hr />
  </div>
</template>
<script>
export default {
  name: "favorites",
  data() {
    return {
      favorite_count: 5,
    };
  },
  methods: {
    changeFavoriteCount() {
      this.favorite_count = this.favorite_count + 2;
      this.emitToParent();
    },
    emitToParent() {
      this.$emit("childToParent", this.favorite_count);
    },
  },
};
</script>

and the App.vue file like this

<template>
    <div class="navbar navbar-expand-md navbar-dark bg-primary">
        <div class="collapse navbar-collapse" id="navbarResponsive">
            <ul class="navbar-nav"> 
                <li class="nav-item">
                    <router-link to="/favorites" class="btn btn-info">
                      
                      <Favorites @childToParent="updateFavorite" />
                      Favorites ( {{ favorite_count }} )
                    </router-link>
                </li>
            </ul>
        </div>
    </div> 
</template>
<script> 
import Favorites from './components/Favorites.vue'
 
export default {
  name: 'App',
  components: {
    Favorites
  },
  data () {
    return { 
      favorite_count: 0, 
    }
  },
  methods: {
    updateFavorite(data) {
      this.favorite_count = data;
    },
  },
}
</script>

Upvotes: 2

Related Questions