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

PHP array and select that work efficiently

Instead of using multiple foreach-statements, I have been struggling with slow page loading when dealing with 26 students in each class, and some subjects having up to 13 'radnummer'. Examples are shown below. This is the desired output format ( ...

Submit button on Ajax form causes automatic page refresh

After adding a simple Ajax form to my WordPress website, I encountered an issue where the validation works fine, but instead of sending the email, the form refreshes after submitting. Here is the code snippet: <script type="text/javascript"> jQ ...

Updating state based on input from a different component

I am attempting to modify the state of the page index in index.js from the Pagination component, Here is my index.js code: import useSWR from 'swr'; import { useState } from 'react'; const Index = ({ data }) => { const ini ...

Tips for retrieving specific values from drop-down menus that have been incorporated into a dynamically-sized HTML table

How can I retrieve individual values from dropdown menus in HTML? These values are stored in a table of unspecified size and I want to calculate the total price of the selected drinks. Additionally, I need the code to be able to compute the price of any ne ...

What is the best way to acquire the href value from this source?

Looking to extract the dynamic value "3 Sent" from the html snippet provided. How can this be achieved? <ul class="nav nav-tabs some-tabs"> <li class="active"> <a href="#accepted" data-toggle="tab">1 Accepted</ ...

Using Django Rest Framework (DRF) to transmit an array of images as a

I need assistance with sending an array of images in a JSON format. My desired output is: {"id":1,"timeIntervel":4,"images":["http://127.0.0.1:8000/images/i1.jpg","http://127.0.0.1:8000/images/i2.jpg","http://127.0.0.1:8000/images/i3.jpg","http://127.0.0. ...

Utilizing withRouter outside a component to navigate through historical data

I'm still getting the hang of react router and encountering some challenges. I can easily use history within a component without any issues. However, when trying to access history from a function outside the component, I run into problems. Despite my ...

Navigating between two intervals in JavaScript requires following a few simple steps

I have created a digital clock with a button that switches the format between AM/PM system and 24-hour system. However, I am facing an issue where both formats are running simultaneously, causing the clocks to change every second. Despite trying various s ...

Enhance the URL with parameters using Vue.js

I am currently working with vuejs3 and I am looking to implement a filter feature. When a user clicks on a specific link, I want to add the selected parameters to the URL and update the browser's address bar initially. Subsequently, I plan to make an ...

Forms for uploading and submitting multiple files

On my single page, I have several file upload forms that are generated in a loop. The issue is that the first file upload control works fine, but the others do not. <div> <form action="/docs/1046/UploadDocument?Id=1046&amp;propertyTypeId ...

Particles.js fails to persist as I scroll down the HTML page

After creating a website page, I incorporated Particles.js for the background. However, when I scroll down, the particles seem to be confined to the initial corner of the screen and do not continue downward. Here are my current particle settings: #particl ...

invoking a PHP function within a JavaScript script

In my collection of essential functions, there is one that I am particularly interested in: //the functions file //........ function user_exists($username){ $username = sanitize($username); $query = mysql_query("SELECT COUNT('user_id') F ...

Is it possible to include numbers and commas in JQuery Validation?

I have implemented a jQuery validation plugin to validate the fields of a form. One specific requirement is to validate a field to only allow commas and numbers. Below is the HTML code snippet: <input type="text" placeholder="Number of Employees" requ ...

Utilizing JavaScript and PHP to dynamically load HTML content on a webpage

Below is the code snippet I'm working with: <?php if ($x == 1){ ?> <b>Some html...</b> <?php } else if ($x==2){ ?> <b> Other html...</b> <?php } ?> Now, I want to create two links (a ...

Disrupting a Program Operation

We are utilizing the gauge Google Chart applet to visually track the failure rates of message transfers on a SOAP interface via AJAX. My goal is to make the page's background flash red and white when the failure rate reaches 50% or higher, and remain ...

Is there a way to reset the dynamic flexslider when a click event occurs?

Seeking a way to refresh the flexslider on a click event. I have embedded the flexslider in a Bootstrap pop-up and need it to update when the user clicks. The issue arises when I try to refresh the slider as it fails to display properly, likely due to losi ...

Unable to turn off X-Powered-By: Express

After attempting to use app.disable("x-powered-by"); without success, I came across some helpful posts on the topic: how to remove X-Powered-By in ExpressJS Can't get rid of header X-Powered-By:Express I am using "express": "^4.16.4" as backend a ...

Timeout for AngularJS Bootstrap UI Modal

I am having some trouble with opening a bootstrap modal using the $timeout function. The issue I am facing is that the modal keeps opening multiple times as the timeout fires repeatedly. Any assistance or suggestions on how to resolve this problem would be ...

Sending axios post requests in succession in Vue.js

I need to execute two post requests, where the second one should only be triggered after the first one receives a response. I tried using async/await but didn't find a satisfactory solution. let changed = false; if(//condition){ changed = true; ...

AngularJS is not showing the dropdown options as expected

I am facing an issue where the dropdown list options are not displaying, even though I am able to fetch the data in the controller but not in HTML. Here is the code snippet: In HTML <select name="nameSelect" id="nameSelect" ng-model="model.name"> ...