Dean
Dean

Reputation: 23

@click individual object from data array within v-for

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!

Upvotes: 2

Views: 544

Answers (2)

Amaarockz
Amaarockz

Reputation: 4684

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}"

Upvotes: 0

NickMcB
NickMcB

Reputation: 917

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'
        }
    }

Upvotes: 1

Related Questions