2

Very new to Vue and js on that matter really, most likely I have missed a basic fundamental issue but I am trying to toggle the class of individually clicked images within my array without all of the images toggling class at the same time.

template :

   <div class="collage-banner">
                <img
                    v-for="image in images"
                    @click="imgSelected()"
                    :alt="image.alt"
                    class="collage"
                    :class="image.class"
                    :src="image.url"
                    :key="image"
                />

js :

export default {

data() {
    return {
        images: [
            { url: img1, class: "img-1", alt: "collage img" },
            { url: img2, class: "img-2", alt: "collage img" },
            { url: img3, class: "img-3", alt: "collage img" },
            { url: img4, class: "img-4", alt: "collage img" },
            { url: img5, class: "img-5", alt: "collage img" },
            { url: img6, class: "img-6", alt: "collage img" },
            { url: img7, class: "img-7", alt: "collage img" },
            { url: img8, class: "img-8", alt: "collage img" }
        ]
    }
},
methods: {
    imgSelected() {
        if (this.images[0].url === img1) {
            this.images[0].class = 'collage-click'
        } else if (this.images[0].url === img2) {
            this.images[0].class = 'img-1'
        }
        if (this.images[1].url === img2) {
            this.images[1].class = 'collage-click'
        } else if (this.images[1].url === img1) {
            this.images[1].class = 'img-2'
        }
    }
}

}

Let me know if further info is needed, I more than likely have gone about this the entirely wrong way! Thanks in advance!

2
  • Are you looking to set a click handler? Can you confirm you are following this vuejs.org/v2/guide/events.html#Method-Event-Handlers Commented Nov 18, 2021 at 15:47
  • Hi, yes I want to set a click handler so if I click on the (for example) second image, only the second image will change it's class Commented Nov 18, 2021 at 15:59

2 Answers 2

1

You can pass the image index into your imgSelected method, and use this to update class for that image.

For example:

Template:

<img
  v-for="(image, index) in images" << updated
  @click="imgSelected(index)" << updated
  :alt="image.alt"
  class="collage"
  :class="image.class"
  :src="image.url"
  :key="image"
/>

Script:

methods: {
    imgSelected (index) { // add index param
            // use index to get relevant image from array
            this.images[index].class = 'collage-click'
    }
}

If you want to remove class from selected images e.g. user clicks image 1, then image 2, you'd have to also loop through your images and reset the class before updating on latest clicked image.

E.g.

methods: {
        imgSelected (index) {
            // reset all image classes
            for (const i in this.images) {
               this.images[i].class = `img${i + 1}` // reset image class e.g. img2 (need to add 1 to index since it will start at 0)
            }
            
            // use index to get relevant image from array
            this.images[index].class = 'collage-click'
        }
    }
Sign up to request clarification or add additional context in comments.

2 Comments

this worked perfectly, much appreciated! If I wanted to make the click event a toggle class instead of add class would it be much different? For example: user clicks image 1, then image 1 again to revert to previous class?
@Dean For that you'd need to change the line setting the class to: this.images[index].class === 'collage-click' ? img${index + 1} ? 'collage-click' This uses, conditional statement to check if the class is already 'collage-click' and if it is sets it to the imgNUMBER class
0

A better approach would be having a flag called clicked in the images array and toggling class based on that Boolean.

data() {
    return {
        images: [
            { url: img1, class: "img-1", clicked: false, alt: "collage img" },
            { url: img2, class: "img-2",clicked: false, alt: "collage img" },
            { url: img3, class: "img-3",clicked: false, alt: "collage img" },
            { url: img4, class: "img-4", clicked: false, alt: "collage img" },
        ]
    }
},
methods: {
    imgSelected (index) { // add index param
            // use index to get relevant image from array
            this.images[index].clicked = !this.images[index].clicked;
    }
}

and in template

<img
  v-for="(image, index) in images" << updated
  @click="imgSelected(index)" << updated
  :alt="image.alt"
  :class="['collage', {`${image.class}`: !image.clicked, 'collage-click': image.clicked}]"
  :src="image.url"
  :key="image"
/>

Note: if you want the collage to always be applied then you can have it in the array. If you don't want the collage class at all and jus wanna toggle between img1 and collage-click, you could jus have an object like

:class="{`${image.class}`: !image.clicked, 'collage-click': image.clicked}"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.