Reputation: 420
I am trying to add a "show-more" button to an array(v-for) of an array (v-for).
<li v-for="(recruiter, key) in recruiters.data" :key="recruiter.id">
<div v-if="recruiter.cities" >
<div v-if="recruiter.cities.length <= 5 || recruiter.id in cities_expand">
<a :href="'/rekryterare/' + city.slug" v-for="(city, index) in recruiter.cities">{{ city.name }}</a>
</div>
<div v-else>
<template v-for="(city, index) in recruiter.cities">
<template v-if="index+1 <= 4">
<a :href="'/rekryterare/sverige/' + city.slug" >{{ city.name }}</a>
</template>
</template>
<a href="#" @click.prevent="cities_expand.push(recruiter.id)" >...</a>
</div>
</div>
</li>
Basically if there is more than 4 items in recruiter.cities
-> show 4 items + "show more"
However - the recruiter.id in cities_expand
does not work/update?
I'm sure there is a better way of solving this - but nothing else came to mind :) Any ideas?
Upvotes: 0
Views: 273
Reputation: 5077
I'm suspect that the problem is the use of the js in operator. The in
operator checks if an object has a key in the object. It does not check if an array has a value.
So when doing recruiter.id in cities_expand
, this checks if recruiter.id
is a key in the array cities_expand
. The keys of an array are the array indices.
This would explain why spam clicking will work because if the recruiter.id
is e.g. 9, then recruiter.id in cities_expand
will only be true if cities_expand
has key 9
i.e. length 10. Which means you would have to click ...
10 times.
Changing
<div v-if="recruiter.cities.length <= 5 || recruiter.id in cities_expand">
to
<div v-if="recruiter.cities.length <= 5 || cities_expand.indexOf(recruiter.id) > -1 ">
should do the trick.
In terms of an alternative solution, I would encapsulate the inner loop in a component and use a computed value for the list. E.g.
Component RecruiterCities
:
<template>
<div v-if="displayCities" >
<a :href="'/rekryterare/' + city.slug" v-for="(city, index) in displayCities" :key="index">{{ city.name }}</a>
<a v-if="!showExpanded && totalCities > maxDisplayCities" href="#" @click.prevent="showExpanded = true" >...</a>
</div>
</template>
<script>
export default {
props: {
recruiterCities: {
type: Array,
default() {
return []
}
}
},
data() {
return {
showExpanded: false,
maxDisplayCities: 4
}
},
computed: {
totalCities() {
return (this.recruiterCities && this.recruiterCities.length) || 0;
},
displayCities() {
if (!this.recruiterCities) {
return [];
}
if (this.showExpanded || this.recruiterCities.length <= this.maxDisplayCities) {
return this.recruiterCities;
}
return this.recruiterCities.slice(0, this.maxDisplayCities);
}
}
}
</script>
and to use it:
<li v-for="(recruiter, key) in recruiters.data" :key="recruiter.id">
<RecruiterCities :recruiter-cities="recruiter.cities"/>
</li>
Upvotes: 1