I want to achieve a Flip card component like the one here by developing a generic Vue Component, but I’m confused about how can I assign a whole face component (front/back) as a back or front face of the card, and how can I lock the flipping property (as an option), an example of the face (front/back) is:
<div id="planflex" :style="style"> <div class="block"> <h2> {{ action_id }} </h2> </div> <div class="block"> <img :src="require(`../assets/legos/2x${size}${color}.png`)" alt="legos" id="lego"> </div> <div class="block " :id="action_id" @click="choose()"> <h3> {{ actor }} </h3> </div> </div>
Can you please tell me how can I achieve that properly? thanks in advance.
The FlipCard.vue
Vue component I have tried to develop:
<template> <div id="flashcard" class="container" @dblclick="toggleCard()"> <transition name="flip"> <div v-bind:key="flipped" class="card"> {{ flipped ? back : front }} </div> </transition> </div> </template> <script> export default { name: "FlipCard", props: { front: { type: Object, required: true }, back: { type: Object, required: true }, flipped: { type: Boolean, default: false, }, }, methods: { toggleCard() { this.flipped = !this.flipped; }, } } </script>
Style.css
<style> body { font-family: 'Montserrat', sans-serif; text-align: center; } ul { padding-left: 0; display: flex; flex-flow: row wrap; } li { list-style-type: none; padding: 10px 10px; transition: all 0.3s ease; } .container { max-width: 100%; padding: 2em; } .card { display: block; width: 150px; height: 175px; padding: 80px 50px; background-color: #51aae5; border-radius: 7px; margin: 5px; text-align: center; line-height: 27px; cursor: pointer; position: relative; color: #fff; font-weight: 600; font-size: 20px; -webkit-box-shadow: 9px 10px 22px -8px rgba(209,193,209,.5); -moz-box-shadow: 9px 10px 22px -8px rgba(209,193,209,.5); box-shadow: 9px 10px 22px -8px rgba(209,193,209,.5); will-change: transform; } li:hover{ transform: scale(1.1); } li:nth-child(-n+3) .card{ background-color: #e65f51; } li:nth-child(2n+1) .card{ background-color: #a17de9; } li:nth-child(4n) .card{ background-color: #feca34; } li:nth-child(5n-2) .card{ background-color: #51aae5; } li:nth-child(4n+4) .card{ background-color: #feca34; } li:nth-child(-7n+7) .card{ background-color: #e46055; } .delete-card { position: absolute; right: 0; top: 0; padding: 10px 15px; opacity: .4; transition: all 0.5s ease; } .delete-card:hover, .error { opacity: 1; transform: rotate(360deg); } .flip-enter-active { transition: all 0.4s ease; } .flip-leave-active { display: none; } .flip-enter, .flip-leave { transform: rotateY(180deg); opacity: 0; } </style>
Advertisement
Answer
Your card face looks good to put into a new component and then flipCard.vue can display that component, front or back, as a dynamic component
flipCard.vue
<div v-bind:key="flipped" class="card"> <component :is="cardSide" /> </div>
<script> import cardFront from "@/components/cardFront.vue"; import cardBack from "@/components/cardBack.vue"; export default { computed: { cardSide() { if (this.flipped) return cardFront; else return cardBack; }, } }; </script>
more detailed codesandbox here.
Another option is to use slots to display dynamic component content.
Parent component
<flip-card> <template v-slot:front> <cardFront /> </template> <template v-slot:back> <cardBack /> </template> </flip-card>
flipCard.vue
<template> <div id="flashcard" class="container" @click="toggleCard()"> <transition name="flip"> <div v-bind:key="flipped" class="card"> <slot v-if="!flipped" name="front"></slot> <slot v-else name="back"></slot> </div> </transition> </div> </template>
another more detailed codesandbox