2

I have an array of images returned from a API in my vue component, iterated and displayed like so:

<span v-for="pic in pics">
   <img :src="'images/'+pic" onmouseover="highlight(pic)" :class="{isHovered = hovered}" />
</span>

In my script:

data(){
    return {
       pics: [],
       hovered: false,
    }
},
methods:{
   highlight(pic){
       this.hovered = true;
  } 
}

In my css

isHovered{
    border: 2px solid red;
    scale: 1.2;
    cursor: pointer;
}

Problem is each time I hover over an image,all the images get the isHovered class. What I intended was to bind only the image hovered on to the isHovered class. What am i doing wrong please. Any guidance will be appreciated.

3 Answers 3

5

I'm reading the OP but I can't find an answer why you can't use only CSS for that? It's a overkill to use Vue's logic for that.

// thanks to @C2486 for the snippet
var app = new Vue({
  el: "#app",
  data() {
    return {
      pics: [{
        img: "https://i.ytimg.com/vi/qV6y1SksAcE/maxresdefault.jpg"
      }, {
        img: "http://www.memorandum.com/wp-content/uploads/2018/05/trunk-club-memorandum-closet-staples-chic-working-girl-professional-women-capsule-wardrobe-10.jpg"
      }, {
        img: "http://www.memorandum.com/wp-content/uploads/2018/07/top-working-women-career-sites-17-680x1020.jpg"
      }]
    }
  }
});
.some-img-class:hover {
  border: 3px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <div>
    <div v-for="(pic,index) in pics">
      {{index+1}}
      <img :src="pic.img" width="60" class="some-img-class" />
    </div>
  </div>
</div>

Sign up to request clarification or add additional context in comments.

6 Comments

I've done this. When you hover over an image all the images get the class.
@banky check the snippet, it only adds class for the hovered image.
@Vucko This indeed seems like the most elegant solution. Sometimes you just need to get back to the basics. One tends to get tunnel vision after using these frameworks for some time :) +1
I also thought this but I confused because of reading headline which is asking How to bind individual elements of a vue array to a class
@C2486 yea, the title seems misleading. If if was some non CSS event then sure, but for a simple hover it's a overkill. Nevertheless, Thanks for the snipper!
|
3

In your code you are trying to trigger hove effect for all image if any one image got hovered , Also you have syntax error to apply class. However there would be many way to achieve this, one way is like below

var app = new Vue({
el:"#app",
data(){
    return {
       pics: [{img:"https://i.ytimg.com/vi/qV6y1SksAcE/maxresdefault.jpg",hovered:false},{img:"http://www.memorandum.com/wp-content/uploads/2018/05/trunk-club-memorandum-closet-staples-chic-working-girl-professional-women-capsule-wardrobe-10.jpg",hovered:false},{img:"http://www.memorandum.com/wp-content/uploads/2018/07/top-working-women-career-sites-17-680x1020.jpg",hovered:false}],
       hovered: false,
    }
},
methods:{
   
 }
});
.isHovered{
  border:3px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div>
<div v-for="(pic,index) in pics">
   {{index+1}}
   <img :src="pic.img" v-on:mouseover="pic.hovered = true" :class="{isHovered:pic.hovered}" v-on:mouseout="pic.hovered = false" width="60"/>
</div>
</div>
</div>

3 Comments

Thanks @c2486. Those pics array are generated dynamically and the length (number of images) varies depending on the product clicked from the products page. This means I have no fore-knowledge of the length of the pics array. How do I structure this?
still that would work, just on more loop to add element hovered:false initially
Thanks for your help
2

That's because you have a single hovered property shared between all your pics. You need to re-write your pics so that each one has it's own hovered state. For example ..

data(){
    return {
       pics: [
          {id: 0, name: 'pic1.jpg', hovered: false},
          {id: 1, name: 'pic2.jpg', hovered: false},
          {id: 2, name: 'pic3.jpg', hovered: false},
          ...
       ]
    }
},
methods:{
   toggleHighlight(pic){
       pic.hovered = !pic.hovered;
  } 
}

Then in your template you can reference the individual hovered states ..

<span v-for="pic in pics">
   <img :src="'images/'+pic.name" onmouseover="toggleHighlight(pic)" :class="{isHovered: pic.hovered}" />
</span>

5 Comments

Thanks @Husam. The pics array are fetched dynamically. What I mean is this, the app is like an e-commerce app, when you click on a product it displays the single product page with the pictures uploaded for that product, so there's no way no know b4hand the number of pics that will be displayed. In this situation, how do I write my pics data pls
@banky If you could share the method wherein you fetch the pics dynamically it would help. But basically in that method you just use map to add a hovered property to each pic before assigning the result to your pics array.
Just a normal axios call. Once a product is clicked on the product page, an axios call is made to the api to fetch the details of the product, including all the pictures uploaded for the product. Here I'm displaying the images and then when I mouse over anyone, I want the class to change.
@banky Okay I suppose at the end of that axios call you're assigning the response to this.pics. Before you do that you can do response.map and assign a new property hovered to each pic. Then you can assign the new mapped response to this.pics
Thanks. That sounds like what I'm looking for. I will implement it and get back to you. Thanks a million

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.