[Vuejs]-How can I show data from 2 level child component by clicking a button in the main instance?

0👍

You will want to bubble up the selected reviews to the top level. I have added an $emit to the updateR method, and a handler on the movie-card tag that calls a new method, updateReview, which populates the appropriate element of added.

I just have it display added, but you could make your button show/hide a div that contains added.

Vue.component('movie-card', {
  props: ['movie', 'title', 'description', 'review'],
  template: `
        <div>
            <h2>{{ title }}</h2>
            <p>{{ description }}</p>
            <link-btn
                v-for="(review, index) in movie.reviews"
                :index="index"
                :review="review"
                key="review"
                @updateIndex="updateI($event)"
                @updateReview="updateR($event)">
            </link-btn>
            <pre>{{ $data }}</pre>
        </div>
    `,
  data() {
    return {
      selectedIndex: '',
      selectedReview: ''
    }
  },
  methods: {
    updateI(e) {
      if (e + 1 === this.selectedIndex) {
        this.selectedIndex = ''
      } else {
        this.selectedIndex = e + 1
      }
    },
    updateR(e) {
      if (e.id === this.selectedReview.id) {
        this.selectedReview = ''
      } else {
        this.selectedReview = e
      }
      this.$emit('update-review', this.selectedReview);
    }
  }
})

Vue.component('link-btn', {
  props: ['index', 'review'],
  template: `
        <a @click="change">{{ review.content }}</a>
    `,
  methods: {
    change() {
      this.$emit('updateIndex', this.index)
      this.$emit('updateReview', this.review)
    }
  }
})

new Vue({
  el: '#app',
  data: {
    added: [],
    movies: [{
        title: 'Regreso al futuro',
        desc: 'Esto es la descripción de Regreso al futuro',
        reviews: [{
            id: 1,
            content: 'Blabla...',
            stars: 2,
            active: false
          },
          {
            id: 2,
            content: 'Blabla...',
            stars: 3,
            active: false
          },
          {
            id: 3,
            content: 'Blabla...',
            stars: 1,
            active: false
          }
        ]
      },
      {
        title: 'Titanic',
        desc: 'Esto es la descripción de Titanic',
        reviews: [{
            id: 1,
            content: 'Blabla...',
            stars: 2,
            active: false
          },
          {
            id: 2,
            content: 'Blabla...',
            stars: 3,
            active: false
          },
          {
            id: 3,
            content: 'Blabla...',
            stars: 1,
            active: false
          }
        ]
      },
      {
        title: 'Blade Runner',
        desc: 'Esto es la descripción de Blade Runner',
        reviews: [{
            id: 1,
            content: 'Blabla...',
            stars: 2,
            active: false
          },
          {
            id: 2,
            content: 'Blabla...',
            stars: 3,
            active: false
          },
          {
            id: 3,
            content: 'Blabla...',
            stars: 1,
            active: false
          }
        ]
      }
    ]
  },
  methods: {
    updateReview(index, review) {
      while (this.added.length < index) {
        this.added.push(null);
      }
      this.added.splice(index, 1, review);
      
    }
  }
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="app">
  <movie-card v-for="(movie, index) in movies" key="index" :movie="movie" :title="movie.title" :description="movie.desc" :review="movie.review" @update-review="updateReview(index, $event)">
  </movie-card>
  <a>BUTTON TO SHOW REVIEWS SELECTED</a>
  <div v-for="r, i in added">
    {{i}}: {{r}}
  </div>
</div>
👤Roy J

Leave a comment