redGarrian
redGarrian

Reputation: 79

Vue.js switch between pictures upon clicking on an image

Hello I am relatively new to Vue and I need some help with some logic to implement.

I have a json file containing information regarding polaroids I took (id, name, image name, etc.), see a snippet below:

[
{
    "id": "PRD1",
    "image": "polaroid_1.jpeg",
    "name": "Natale - 2020",
    "description": "blah blah blah"
},

{
    "id": "PRD2",
    "image": "polaroid_2.jpeg",
    "name": "A love that never was - 2021",
    "description": "Before the first ever heartbreak of my life (the worst so far)."
},
...    
]

The way the images are rendered are using a v-for within a component I created. Below is the full HTML code:

<template>
<div class="images-wrapper">
    <div class="images" v-for="polaroid in polaroids" :key="polaroid">
        <img class="polaroid-image" :src="getImgUrl(polaroid.image)"/>
        <div class="information-wrapper"> 
            <div class="polaroid-title">
                {{ polaroid.name }}
            </div>
            <div class="polaroid-description">
                {{ polaroid.description }}
            </div>
        </div>
    </div>
</div>

These images are correctly rendered one by one in a grid within my Vue app. What I am struggling to understand, is how to implement the logic that upon clicking on one of the images, or multiple ones, these individual clicked images are substituted by another image (one representing the back of them saved in the assets folder under polaroid_0.jpeg), and display the polaroid.name and polaroid.description belonging to those specifically clicked images.

Does any one have any ideas?

EDIT - What I need

@FayçalBorsali Sorry for the confusion. Imagine I have 3 images in my grid. What I want to do is click on one of the images and have the clicked image substituted by another one, which will also display some extra text (polaroid.name and polaroid.description). If I then click this image again, it will show the original image the app was rendered with. This is what I'm trying to achieve. Is it possible to allow multiple selections at once? i.e. click 2 different images so these are substituted by another one and have the third image stay the same

Upvotes: 0

Views: 981

Answers (2)

Fay&#231;al Borsali
Fay&#231;al Borsali

Reputation: 424

There a multiple ways of doing what you desire, I would suggest

  1. Track if an image is clicked or not (for example by Adding a boolean field to each of your polaroids and whenever you click an image, you toggle that field)

  2. Your :src should be dynamic, this could either be done in the getImgUrl() or by having another field for the image to display when selected

For example, polaroids become :

[
{
    "id": "PRD1",
    "image": "polaroid_1.jpeg",
    "name": "Natale - 2020",
    "description": "blah blah blah",
    "show" : false,
    "clickedImage" : "polaroid_1.jpeg"
},

{
    "id": "PRD2",
    "image": "polaroid_2.jpeg",
    "name": "A love that never was - 2021",
    "description": "Before the first ever heartbreak of my life (the worst so far).",
    "show" : false,
    "clickedImage" : "polaroid_1.jpeg"
},
...    
]

Your template may become :

<template>
<div class="images-wrapper">
    <div class="images" v-for="polaroid in polaroids" :key="polaroid" @click="toggleImg(polaroid.id)">
        <img class="polaroid-image" :src="getImgUrl(polaroid)"/>
        <div class="information-wrapper"> 
            <div class="polaroid-title">
                {{ polaroid.name }}
            </div>
            <div class="polaroid-description">
                {{ polaroid.description }}
            </div>
        </div>
    </div>
</div>

and in your code,

function getImgUrl(polaroid) {
  cont img = polaroid.show ? polaroid.clickedImg : polaroid.img;
  // Your current code
} 

These are just examples, but the general approach is my first two points

Upvotes: 1

yoduh
yoduh

Reputation: 14639

If I understand right, I think you just want to use a v-if and v-else to display either the current image or the "back" image using a boolean property you'll need to add to each polaroid object. A click event listener can handle changing the boolean back and forth. The information-wrapper's display can be tied to the same boolean if you only want it displayed when the back image is shown.

<template>
<div class="images-wrapper">
    <div class="images" v-for="polaroid in polaroids" :key="polaroid">
        <img v-if="polaroid.show" @click="polaroid.show = false" class="polaroid-image" :src="getImgUrl(polaroid.image)"/>
        <img v-else @click="polaroid.show = true" class="polaroid-image" :src="getImgUrl('polaroid_0.jpeg')"/>
        <div v-if="!polaroid.show" class="information-wrapper"> 
            <div class="polaroid-title">
                {{ polaroid.name }}
            </div>
            <div class="polaroid-description">
                {{ polaroid.description }}
            </div>
        </div>
    </div>
</div>

new boolean added to each polaroid object:

{
    "id": "PRD1",
    "image": "polaroid_1.jpeg",
    "name": "Natale - 2020",
    "description": "blah blah blah",
    "show": true
}

Upvotes: 1

Related Questions