I tried it like this:
<template>
...
<b-card-group deck v-for="row in formattedClubs">
<b-card v-for="club in row"
img-src="http://placehold.it/130?text=No-image"
img-alt="Img"
img-top>
<h4 class="card-title"
@mouseover="showAll = true"
@mouseout="showAll = false">
{{getWord(club.description)}}
</h4>
<p class="card-text">
{{club.price}}
</p>
<p class="card-text">
{{club.country}}
</p>
<div slot="footer">
<b-btn variant="primary" block>Add</b-btn>
</div>
</b-card>
</b-card-group>
...
</template>
<script>
export default {
data () {
return {
showAll: false,
clubs: [
{id:1, description:'chelsea is the best club in the world and chelsea has a great player', price:1000, country:'england'},
{id:2, description:'liverpool has salah', price:900, country:'england'},
{id:3, description:'mu fans', price:800, country:'england'},
{id:4, description:'city has a great coach. Thas is guardiola', price:700, country:'england'},
{id:5, description:'arsenal player', price:600, country:'england'},
{id:6, description:'tottenham in london', price:500, country:'england'},
{id:7, description:'juventus stadium', price:400, country:'italy'},
{id:8, description:'madrid sell ronaldo', price:300, country:'spain'},
{id:9, description:'barcelona in the spain', price:200, country:'spain'},
{id:10, description:'psg buys neymar at a fantastic price', price:100, country:'france'}
]
}
},
computed: {
formattedClubs () {
return this.clubs.reduce((c, n, i) => {
if (i % 4 === 0) c.push([]);
c[c.length - 1].push(n);
return c;
}, []);
}
},
methods: {
getWord (desc) {
if (this.showAll) return desc
let value = desc;
let length = 30;
if (value.length <= length) {
return value;
} else {
return value.substring(0, length) + '...';
}
}
}
}
</script>
That almost works. But when I hover over the description in box 1, the description on all the other boxes also hover. It should only hover showing the truncated text on the box 1.
How can I solve this problem?
You can create an array of boolean where each value corresponds to a team.
You have the initial team array. You can create an array of the same size with values initialised to false.
In your template
Now you can match a team in the array
formattedClubs[index]
with a value inshowDescription[index]
Same in your events.
Try using key attribute for each item. If you set a mouseover for showAll, it will certainly display all the descriptions as it will return true for all. That's why, you should do dynamic list rendering here that Vue supports, similarly like this:
Also, I recommend you to have a look at the official documentation about dynamic list rendering :
https://vuejs.org/v2/guide/list.html
The problem is that you have only one property to control the truncation of all items.
Firstly, you need to ensure that each club has its own boolean to control the text truncation. Lets use your already existing computed property to add a new reactive property for each club:
Secondly, let's use the
<template>
to handle visual things, keeping the right separation of concerns, using the new individualclub.truncate
property with av-if
/v-else
block:And now, the
trucateText
method only needs to care about returning the truncated text, since it's only called if we're truncating a description of one club:Take a look at the fully working code here if any doubts persists.