Home > Enterprise >  Show extra card from v-for list of cards
Show extra card from v-for list of cards

Time:07-19

I'm trying to show a card with extra information for each card inside a v-for loop.

<template>
    <div v-for="card in cards">
        <card>
            <!-- card content with information -->
            <button @click="viewExtra" />
        </card>
        <card v-if="card.infoExtra && showExtra>
            <!-- card content with extra information -->
        </card>
    </div>
</template>
<script>
    export default {
        data: () => ({
            cards: [] // Array with cards and information
            ,showExtra: false 
        }),
        methods: {
            viewExtra() {
                this.showExtra = !this.showExtra;
            }
    }
</script>

It should only show extra card if principal card contains extra information (card.infoExtra) but it's showing for all cards that have infoExtra, not for the one on which I click the button.

Here's what I've done so far:

enter image description here

What am I doing wrong.

Thanks in advance.

CodePudding user response:

My understanding was wrong, No need to add a separate property in each object as each card component will contains their own scope and render separately. Hence, single variable showExtra will work perfectly.

Here is the live Demo :

Vue.component('card', {
    data() {
        return {
            showExtra: false
        }
    },
    template: `
        <div >
            <p>{{ cardinfo }}</p>
            <button @click="viewExtra">View Extra</button>
            <p v-if="extrainfo && showExtra">
                {{ extrainfo }}
            </p>
        </div>
    `,
    props: ['cardinfo', 'extrainfo'],
    methods: {
        viewExtra() {
            this.showExtra = !this.showExtra;
        }
    }
});

new Vue({
    el: '#container',
    data: {
        cards: [{
            id: 1,
            cardInfo: 'This is the content for Card 1',
            infoExtra: 'Extra infor for Card 1'
        }, {
            id: 2,
            cardInfo: 'This is the content for Card 2',
            infoExtra: 'Extra infor for Card 2'
        }, {
            id: 3,
            cardInfo: 'This is the content for Card 3',
            infoExtra: 'Extra infor for Card 3'
        }, {
            id: 4,
            cardInfo: 'This is the content for Card 4',
            infoExtra: 'Extra infor for Card 4'
        }]
    }
});
#container {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    margin: auto;
    background: grey;
    width: 750px;
    opacity: .5;
    border-radius: 3px;
    margin-top: 50px;
    padding: 10px;
}

.card {
    width: 20%;
    height: 180px;
    align-self: center;
    background: whitesmoke;
    padding: 5px;
    border-radius: 3px;
    margin: 10px 10px;
    font-family: monospace;
    transition: all .15s ease-in-out;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.min.js"></script>
<main id="container">
    <card v-for="card in cards" :key="card.id"
                :cardinfo="card.cardInfo" :extrainfo="card.infoExtra">
    </card>
</main>

CodePudding user response:

Since you have mutual showExtra state when you toggle it to true, all cards will show extra information.

You should have had showExtra state for individual for each card

async created() {
  try {
    const response = await this.$api.getCard()
    this.cards = [...response?.data?.map(i => ({
      showExtra: false,   // attach state for each card, initially to false
      ...i,
    }))]
  } catch (err) {
    // do something
  }
}
<template>
  <div v-for="card in cards">
    <card>
      <!-- card content with information -->
      <button @click="card.showExtra = true" />  <!-- toggle it -->
    </card>
    <card v-if="card.infoExtra && card.showExtra>
      <!-- card content with extra information -->
    </card>
  </div>
</template>

CodePudding user response:

showExtra should be in every card object,You can't share one

  • Related