Reputation: 3591
I can't figure out how to properly select (set active class) when I do v-for loop and one class is already selected. Let me share the code and with further explanation
These are my available subscriptions and one is already selected, based on user data
<ul>
<li v-for="(s, key, index) in subscriptions"
:class="checkIfClassActive(s.subscription_key)"
@click="setActive(key, index)">
{{ s.name }}
</li>
</ul>
and my js code
checkIfClassActive(userSubscriptionKey) {
if (userSubscriptionKey === this.userSubscription.subscription_key) {
return 'active';
}
},
setActive(key, index) {
},
Now the next step is when I click on one li element it should become active and all other li elements should lose active class, but the problem is that I can't figure out how to properly write setActive function. Can you please help me out, how to do this.
If you need any additional informations, let me know and I will provide. Thank you!
Upvotes: 7
Views: 27219
Reputation: 456
I had this problem the simplest answer is to change the "li" tags to "router-link", then change the default styling of the router-link. In this case "router-link-active"
<ul>
<router-link v-for="item in items"
:key="item.id"
:to="item.route"
>
{{ s.name }}
</router-link>
</ul>
<style>
.router-link-active{
...
}
</style>
Upvotes: 0
Reputation: 11
this is quicly
if you use v-for:
<template>
<div>
<ul>
<li
class="anyThings"
v-for="cat in cats"
:key="cat.index"
@click="itemActive(cat.index)"
:class="[(itemA == cat.index) ? 'active':'']"
>{{ cat.yourObjectKey }}
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
itemA:'0' // for first load and in curent path
}
},
computed: {
cats() {
...
}
},
methods: {
itemActive(e) {
this.itemA = e;
}
},
}
</script>
<style>
.active {
...
}
</style>
if you don't need use v-for and use router-link in element:
<template>
<div>
<ul>
<li @click="itemActive($route.path)">
<router-link to="/" class="anyThings"
:class="[(itemA == '/') ? 'active':'']"
>your text
</router-link>
</li>
<li @click="itemActive($route.path)">
<router-link to="/article" class="anyThings"
:class="[(itemA == '/article') ? 'active':'']"
>your text
</router-link>
</li>
.
.
.
</ul>
</div>
</template>
<script>
export default {
data() {
return {
itemA:this.$route.path // for first load and in curent path
}
},
methods: {
itemActive(e) {
this.itemA = e;
}
},
}
</script>
<style>
.active {
...
}
</style>
Upvotes: 1
Reputation: 3653
Add a data
property called activeIndex
:
data() {
return {
activeIndex: undefined
}
},
and your setActive
method:
methods: {
setActive(subscription, index) {
this.activeIndex = index;
this.userSubscription.subscription_key = subscription.subscription_key
},
getSubscriptions() {
.....
// fetch subscriptions in this.subscriptions var
.....
// select preselected subscription, when fetching subscriptions
let userSubscriptionKey = this.userSubscription.subscription_key;
let indexOfObject = this.subscriptions.findIndex(
o => o.subscription_key === userSubscriptionKey
);
this.setActive(this.userSubscription, indexOfObject);
}
}
with a slight modification to your template:
<ul>
<li v-for="(s, index) in subscriptions"
:class="{ 'active': activeIndex === index }" :key="s.id"
@click="setActive(s, index)">
{{ s.name }}
</li>
</ul>
You basically set an index that should be active and that's it. active
css class is added when list element's index is the same as activeIndex
.
As for setting activeIndex
to existing choice before the user changes it, you can set activeIndex
when fetching subscriptions data to user's current subscription.
Fiddle: http://jsfiddle.net/eywraw8t/256701/
Upvotes: 28
Reputation: 27719
A simple example showing the logic:
html part:
<div id="app">
<ul>
<li
v-for="item in items"
:key="item.id"
:class="item.class"
@click="set_active_id(item.id)"
>{{ item.text }}</li>
</ul>
</div>
Js part:
new Vue({
el: "#app",
data: {
items: [
{ id: 1, text: 'text1', class: 'active' }, //default active
{ id: 2, text: 'text2', class: '' },
{ id: 3, text: 'text3', class: '' }
],
previous_active_id: 1
},
methods: {
set_active_id(id) {
if (this.previous_active_id === id) return //no need to go further
this.items.find(item => item.id === this.previous_active_id).class = '' //remove the active class from old active li
this.items.find(item => item.id === id).class = 'active' //set active class to new li
this.previous_active_id = id //store the new active li id
}
}
})
Upvotes: 1
Reputation: 2920
Change your this.userSubscription.subscription_key
variable everytime a tab is selected. For this pass it through setActive(s.subscription_key)
You can do something like this,
<li v-for="(s, key, index) in subscriptions"
:class="checkIfClassActive(s.subscription_key)"
@click="setActive(s.subscription_key)">
{{ s.name }}
</li>
Js
checkIfClassActive(userSubscriptionKey) {
if (userSubscriptionKey === this.userSubscription.subscription_key) {
return 'active';
}
},
setActive(subscription_key) {
this.userSubscription.subscription_key=subscription_key;
},
Upvotes: 4