Is there a way for me to display information from a secondary child component by simply clicking a button on the main component instance?

Consider a scenario where there is a main instance, a child component named "movie-card," and another child component within "movie-card" called "link-btn." The objective is to create a selector that loops through the "link-btn" component using v-for. Additionally, there should be a button in the main instance that displays the data selected from each "link-btn" component. Below is the code snippet:

HTML:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
        <title>Test</title>
    </head>
    <body>
        <div id="app">
            <movie-card
                v-for="(movie, index) in movies"
                key="index"
                :movie="movie"
                :title="movie.title"
                :description="movie.desc"
                :review="movie.review">
            </movie-card>
            <a>BUTTON TO SHOW REVIEWS SELECTED</a>
        </div>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.js"></script>
        <script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="275152425f671509130917">[email protected]</a>/dist/vuex.js"></script>
        <script src="app.js"></script>
    </body>
</html>

JavaScript:

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
            }
        }
    }
})

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: 'Back to the Future',
                desc: 'This is the description of Back to the Future',
                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: 'This is the description of 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: 'This is the description of 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 }
                ]
            }
        ]
    }
})

Answer №1

To prioritize the selected reviews, you should implement a method to bring them to the forefront. I have introduced an $emit in the updateR function, and attached a handler to the movie-card tag that invokes a new method called updateReview, which fills the appropriate element of added.

Currently, it only displays added, but you could enhance it by making your button toggle a div containing 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: 'Back to the Future',
        desc: 'This is the description of Back to the Future',
        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: 'This is the description of 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: 'This is the description of 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>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to transfer an id from one const to another in JavaScript?

I have 2 APIs that I am using to fetch data. The first API, called getDetails, is used to retrieve student details. Within these student details, there is an ID that needs to be fetched from the second API and displayed in the first API. The second API is ...

Developing Functions using MongoDB Console

When running the query db.graduates.find({student_id: '2010-01016'}).pretty(), it returns a result. Afterwards, I created a function: function findStud(name,value){ return db.graduates.find({name:value}); } However, while executing findStud("s ...

What categories do input events fall into within Vue?

What Typescript types should be used for input events in Vue to avoid missing target value, key, or files properties when using Event? For example: <input @input="(e: MISSING_TYPE) => {}" /> <input @keypress="(e: MISSING_TYPE) = ...

Is there a way to implement a function in Javascript or CSS where hovering over a button will cause a div to scroll either left or right

I am working on creating a unique photo gallery layout with a description block positioned below the images. My goal is to incorporate two arrow buttons, one on each side of the photos, that will trigger a scrolling effect when hovered over - shifting the ...

Listener of events calculates the outcome

In need of help with retrieving the current coordinates of a clicked point on Google Maps. Here is my code snippet: let latLng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude); getCoords() { google.maps.event.addListener ...

Unable to make a post using vue.js

I am facing an issue while trying to submit form data using "vue-resource" in my code. The error message I receive mentions a problem with the use of this method alongside vue-cli and vuetify. Error [Vue warn]: Error in v-on handler: "TypeError: this.$h ...

Animating slides with CSS Keyframes and React, incorporating toggle slide fade out and slide fade (back) in

I am seeking a solution for toggling a box (div) with slide-out animation and then sliding back in animation (in reverse) upon button press. My requirement is to have no animations during the initial page render. While I can successfully slide the box to ...

What is the best way to view all of the objects in an array?

My challenge involves an array consisting of ten objects, each with six properties to be displayed on a view. I want users to have the ability to update these properties by entering new data into inputs. How can I efficiently monitor the entire array to ...

Can you explain the concept of an environment variable in the context of Node/Express?

This question may seem basic, but I haven't found a clear explanation for it yet. In my experience with Node/Express, I always set the following variable: var port = PROCESS.env.PORT || 9000 I understand that PROCESS.env.PORT is related to environme ...

Vue.js: The chart's dataset has been refreshed

I am utilizing vue-chart.js to create a basic chart. import { Line } from 'vue-chartjs'; export default { extends: Line, mounted() { this.renderChart({ labels: [this.getChartLabels], datasets: [ { label: &a ...

Updating a nested subarray using Node.js with the MongoDB API

I am currently in the process of developing a backend API using Node.js/Express and MongoDB for managing student records. I am facing difficulty with updating a sub-field within the data structure. Below is the code snippet from my Student.js file located ...

Modify the collapse orientation in Bootstrap

I would like the button to expand from the bottom when clicked and collapse back down, instead of behaving like a dropdown. <head> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_ ...

Angular throws an error when trying to parse undefined data outside of an async function

I'm having trouble parsing data retrieved from an http call and passing it to ngOnInit. Can you assist me in finding a solution? My project is built with Angular 4. Here's the async function: async getAsyncData() { this.asyncResult = awai ...

Finding the host name of a client machine using Node.js

Is there anyone who can assist me in obtaining the client's machine name or host name for authentication on my website, which is operating internally within my company domain? I attempted the code below but received the server's host name instead ...

(NodeJS + Socket IO Issue) NodeJS is sending duplicate data when the page is refreshed, causing an improper response

Each time I refresh a page, NodeJS seems to be repetitively writing data on the socket. Interestingly, the number of writes increases with each page refresh but then stabilizes at three after several refreshes. I urge you to inspect the console output whi ...

Taking data input from three textboxes and storing them in a PHP array

In my HTML form, I have 3 text input fields and one submit button. Each text field is intended for entering the name of an animal, which should then be saved into a PHP array. Here is the structure of my HTML form: <form action="Test.php" method="post ...

Ways to validate an element in an Array using Cypress dynamically

I have a question regarding the dynamic verification of Array elements. For my project, I need to suggest a price that will increase over time, and I require a script that can verify these elements dynamically. In the screenshot provided, you can see what ...

Clear HTML

Is there a way to create a 'div' element in an HTML document and adjust the background transparency using CSS or Javascript/JQuery in order to achieve a look similar to Simple Calendar Widget or Glass Widgets from Android? I have tried using the ...

Tips for integrating the C++ icon into a ReactJs project

For a ReactJs project, I needed to include icons of different Languages and Tools. When adding a Python icon, I used: <ListItem> <ListItemIcon className={classes.icon}> <span className="iconify" data-icon= ...

Navigating through VueJS: Understanding the Routing Concept

Here's a query that might seem silly, especially since I'm unsure if I'm working with VueJS or VueJS 2.0. I'm attempting to implement basic routing functionality where I can access the parameters or path from the URL. For instance **** ...