How does toggle a class in vue.js?
I have the following:
<th class="initial " v-on="click: myFilter">
<span class="wkday">M</span>
</th>
new Vue({
el: '#my-container',
data: {},
methods: {
myFilter: function(){
// some code to filter users
}
}
});
When I click th
I want to apply active
as a class as follows:
<th class="initial active" v-on="click: myFilter">
<span class="wkday">M</span>
</th>
This needs to toggle i.e. each time its clicked it needs to add/remove the class.
1.
@click="$event.target.classList.toggle('active')"
2.
:class="{ active }"
@click="active = !active"
3.
:class="'initial ' + (active ? 'active' : '')"
@click="active = !active"
4.
:class="['initial', { active }]"
@click="active = !active"
Reference link: https://vuejs.org/v2/guide/class-and-style.html
Demo:
new Vue({_x000D_
el: '#app1'_x000D_
});_x000D_
_x000D_
new Vue({_x000D_
el: '#app2',_x000D_
data: { active: false }_x000D_
});_x000D_
_x000D_
new Vue({_x000D_
el: '#app3',_x000D_
data: { active: false }_x000D_
});_x000D_
_x000D_
new Vue({_x000D_
el: '#app4',_x000D_
data: { active: false }_x000D_
});
_x000D_
.initial {_x000D_
width: 300px;_x000D_
height: 100px;_x000D_
background: gray;_x000D_
}_x000D_
_x000D_
.active {_x000D_
background: red;_x000D_
}
_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>_x000D_
_x000D_
<!-- directly manipulation: not recommended -->_x000D_
<div id="app1">_x000D_
<button _x000D_
class="initial" _x000D_
@click="$event.target.classList.toggle('active')"_x000D_
>$event.target.classList.toggle('active')</button>_x000D_
</div>_x000D_
_x000D_
<!-- binding by object -->_x000D_
<div id="app2">_x000D_
<button _x000D_
class="initial" _x000D_
:class="{ active }"_x000D_
@click="active = !active"_x000D_
>class="initial" :class="{ active }"</button>_x000D_
</div>_x000D_
_x000D_
<!-- binding by expression -->_x000D_
<div id="app3">_x000D_
<button _x000D_
:class="'initial ' + (active ? 'active' : '')" _x000D_
@click="active = !active"_x000D_
>'initial ' + (active ? 'active' : '')</button>_x000D_
</div>_x000D_
_x000D_
<!-- binding with object combined array -->_x000D_
<div id="app4">_x000D_
<button _x000D_
:class="['initial', { active }]" _x000D_
@click="active = !active"_x000D_
>['initial', { active }]</button>_x000D_
</div>
_x000D_
This answer relevant for Vue.js version 2
<th
class="initial "
v-on:click="myFilter"
v-bind:class="{ active: isActive }"
>
<span class="wkday">M</span>
</th>
The rest of the answer by Douglas is still applicable (setting up the new Vue instance with isActive: false
, etc).
Relevant docs: https://vuejs.org/v2/guide/class-and-style.html#Object-Syntax and https://vuejs.org/v2/guide/events.html#Method-Event-Handlers
I've got a solution that allows you to check for different values of a prop and thus different <th>
elements will become active/inactive. Using vue 2 syntax.
<th
class="initial "
@click.stop.prevent="myFilter('M')"
:class="[(activeDay == 'M' ? 'active' : '')]">
<span class="wkday">M</span>
</th>
...
<th
class="initial "
@click.stop.prevent="myFilter('T')"
:class="[(activeDay == 'T' ? 'active' : '')]">
<span class="wkday">T</span>
</th>
new Vue({
el: '#my-container',
data: {
activeDay: 'M'
},
methods: {
myFilter: function(day){
this.activeDay = day;
// some code to filter users
}
}
})
for nuxt link and bootstrap v5 navbar-nav, I used a child component
<nuxt-link
@click.prevent.native="isDropdwonMenuVisible = !isDropdwonMenuVisible"
to=""
:title="item.title"
:class="[item.cssClasses, {show: isDropdwonMenuVisible}]"
:id="`navbarDropdownMenuLink-${index}`"
:aria-expanded="[isDropdwonMenuVisible ? true : false]"
class="nav-link dropdown-toggle"
aria-current="page"
role="button"
data-toggle="dropdown"
>
{{ item.label }}
</nuxt-link>
data() {
return {
isDropdwonMenuVisible: false
}
},
Try :
<template>
<th :class="'initial '+ active" v-on="click: myFilter">
<span class="wkday">M</span>
</th>
</template>
<script lang="ts">
active:string=''
myFilter(){
this.active='active'
}
</script>
<style>
.active{
/***your action***/
}
</style>
Without the need of a method:
// html element, will display'active' class if showMobile is true
//clicking on the elment will toggle showMobileMenu to true and false alternatively
<div id="mobile-toggle"
:class="{ active: showMobileMenu }"
@click="showMobileMenu = !showMobileMenu">
</div>
//in your vue.js app
data: {
showMobileMenu: false
}
new Vue({_x000D_
el: '#fsbar',_x000D_
data:{_x000D_
isActive: false_x000D_
},_x000D_
methods: {_x000D_
toggle: function(){_x000D_
this.isActive = !this.isActive;_x000D_
}_x000D_
}_x000D_
});
_x000D_
/*_x000D_
DEMO STYLE_x000D_
*/_x000D_
@import "https://fonts.googleapis.com/css?family=Poppins:300,400,500,600,700";_x000D_
_x000D_
_x000D_
body {_x000D_
font-family: 'Poppins', sans-serif;_x000D_
background: #fafafa;_x000D_
}_x000D_
_x000D_
p {_x000D_
font-family: 'Poppins', sans-serif;_x000D_
font-size: 1.1em;_x000D_
font-weight: 300;_x000D_
line-height: 1.7em;_x000D_
color: #999;_x000D_
}_x000D_
_x000D_
a, a:hover, a:focus {_x000D_
color: inherit;_x000D_
text-decoration: none;_x000D_
transition: all 0.3s;_x000D_
}_x000D_
_x000D_
.navbar {_x000D_
padding: 15px 10px;_x000D_
background: #fff;_x000D_
border: none;_x000D_
border-radius: 0;_x000D_
margin-bottom: 40px;_x000D_
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.1);_x000D_
}_x000D_
_x000D_
.navbar-btn {_x000D_
box-shadow: none;_x000D_
outline: none !important;_x000D_
border: none;_x000D_
}_x000D_
_x000D_
.line {_x000D_
width: 100%;_x000D_
height: 1px;_x000D_
border-bottom: 1px dashed #ddd;_x000D_
margin: 40px 0;_x000D_
}_x000D_
_x000D_
i, span {_x000D_
display: inline-block;_x000D_
}_x000D_
_x000D_
/* ---------------------------------------------------_x000D_
SIDEBAR STYLE_x000D_
----------------------------------------------------- */_x000D_
.wrapper {_x000D_
display: flex;_x000D_
align-items: stretch;_x000D_
}_x000D_
_x000D_
#sidebar {_x000D_
min-width: 250px;_x000D_
max-width: 250px;_x000D_
background: #7386D5;_x000D_
color: #fff;_x000D_
transition: all 0.3s;_x000D_
}_x000D_
_x000D_
#sidebar.active {_x000D_
min-width: 80px;_x000D_
max-width: 80px;_x000D_
text-align: center;_x000D_
}_x000D_
_x000D_
#sidebar.active .sidebar-header h3, #sidebar.active .CTAs {_x000D_
display: none;_x000D_
}_x000D_
_x000D_
#sidebar.active .sidebar-header strong {_x000D_
display: block;_x000D_
}_x000D_
_x000D_
#sidebar ul li a {_x000D_
text-align: left;_x000D_
}_x000D_
_x000D_
#sidebar.active ul li a {_x000D_
padding: 20px 10px;_x000D_
text-align: center;_x000D_
font-size: 0.85em;_x000D_
}_x000D_
_x000D_
#sidebar.active ul li a i {_x000D_
margin-right: 0;_x000D_
display: block;_x000D_
font-size: 1.8em;_x000D_
margin-bottom: 5px;_x000D_
}_x000D_
_x000D_
#sidebar.active ul ul a {_x000D_
padding: 10px !important;_x000D_
}_x000D_
_x000D_
#sidebar.active a[aria-expanded="false"]::before, #sidebar.active a[aria-expanded="true"]::before {_x000D_
top: auto;_x000D_
bottom: 5px;_x000D_
right: 50%;_x000D_
-webkit-transform: translateX(50%);_x000D_
-ms-transform: translateX(50%);_x000D_
transform: translateX(50%);_x000D_
}_x000D_
_x000D_
#sidebar .sidebar-header {_x000D_
padding: 20px;_x000D_
background: #6d7fcc;_x000D_
}_x000D_
_x000D_
#sidebar .sidebar-header strong {_x000D_
display: none;_x000D_
font-size: 1.8em;_x000D_
}_x000D_
_x000D_
#sidebar ul.components {_x000D_
padding: 20px 0;_x000D_
border-bottom: 1px solid #47748b;_x000D_
}_x000D_
_x000D_
#sidebar ul li a {_x000D_
padding: 10px;_x000D_
font-size: 1.1em;_x000D_
display: block;_x000D_
}_x000D_
#sidebar ul li a:hover {_x000D_
color: #7386D5;_x000D_
background: #fff;_x000D_
}_x000D_
#sidebar ul li a i {_x000D_
margin-right: 10px;_x000D_
}_x000D_
_x000D_
#sidebar ul li.active > a, a[aria-expanded="true"] {_x000D_
color: #fff;_x000D_
background: #6d7fcc;_x000D_
}_x000D_
_x000D_
_x000D_
a[data-toggle="collapse"] {_x000D_
position: relative;_x000D_
}_x000D_
_x000D_
a[aria-expanded="false"]::before, a[aria-expanded="true"]::before {_x000D_
content: '\e259';_x000D_
display: block;_x000D_
position: absolute;_x000D_
right: 20px;_x000D_
font-family: 'Glyphicons Halflings';_x000D_
font-size: 0.6em;_x000D_
}_x000D_
a[aria-expanded="true"]::before {_x000D_
content: '\e260';_x000D_
}_x000D_
_x000D_
_x000D_
ul ul a {_x000D_
font-size: 0.9em !important;_x000D_
padding-left: 30px !important;_x000D_
background: #6d7fcc;_x000D_
}_x000D_
_x000D_
ul.CTAs {_x000D_
padding: 20px;_x000D_
}_x000D_
_x000D_
ul.CTAs a {_x000D_
text-align: center;_x000D_
font-size: 0.9em !important;_x000D_
display: block;_x000D_
border-radius: 5px;_x000D_
margin-bottom: 5px;_x000D_
}_x000D_
_x000D_
a.download {_x000D_
background: #fff;_x000D_
color: #7386D5;_x000D_
}_x000D_
_x000D_
a.article, a.article:hover {_x000D_
background: #6d7fcc !important;_x000D_
color: #fff !important;_x000D_
}_x000D_
_x000D_
_x000D_
_x000D_
/* ---------------------------------------------------_x000D_
CONTENT STYLE_x000D_
----------------------------------------------------- */_x000D_
#content {_x000D_
padding: 20px;_x000D_
min-height: 100vh;_x000D_
transition: all 0.3s;_x000D_
}_x000D_
_x000D_
_x000D_
/* ---------------------------------------------------_x000D_
MEDIAQUERIES_x000D_
----------------------------------------------------- */_x000D_
@media (max-width: 768px) {_x000D_
#sidebar {_x000D_
min-width: 80px;_x000D_
max-width: 80px;_x000D_
text-align: center;_x000D_
margin-left: -80px !important ;_x000D_
}_x000D_
a[aria-expanded="false"]::before, a[aria-expanded="true"]::before {_x000D_
top: auto;_x000D_
bottom: 5px;_x000D_
right: 50%;_x000D_
-webkit-transform: translateX(50%);_x000D_
-ms-transform: translateX(50%);_x000D_
transform: translateX(50%);_x000D_
}_x000D_
#sidebar.active {_x000D_
margin-left: 0 !important;_x000D_
}_x000D_
_x000D_
#sidebar .sidebar-header h3, #sidebar .CTAs {_x000D_
display: none;_x000D_
}_x000D_
_x000D_
#sidebar .sidebar-header strong {_x000D_
display: block;_x000D_
}_x000D_
_x000D_
#sidebar ul li a {_x000D_
padding: 20px 10px;_x000D_
}_x000D_
_x000D_
#sidebar ul li a span {_x000D_
font-size: 0.85em;_x000D_
}_x000D_
#sidebar ul li a i {_x000D_
margin-right: 0;_x000D_
display: block;_x000D_
}_x000D_
_x000D_
#sidebar ul ul a {_x000D_
padding: 10px !important;_x000D_
}_x000D_
_x000D_
#sidebar ul li a i {_x000D_
font-size: 1.3em;_x000D_
}_x000D_
#sidebar {_x000D_
margin-left: 0;_x000D_
}_x000D_
#sidebarCollapse span {_x000D_
display: none;_x000D_
}_x000D_
}
_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>_x000D_
<!DOCTYPE html>_x000D_
<html>_x000D_
<head>_x000D_
<meta charset="utf-8">_x000D_
<meta name="viewport" content="width=device-width, initial-scale=1.0">_x000D_
<meta http-equiv="X-UA-Compatible" content="IE=edge">_x000D_
_x000D_
<title>Collapsible sidebar using Bootstrap 3</title>_x000D_
_x000D_
<!-- Bootstrap CSS CDN -->_x000D_
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">_x000D_
<!-- Our Custom CSS -->_x000D_
<link rel="stylesheet" href="style4.css">_x000D_
</head>_x000D_
<body>_x000D_
_x000D_
_x000D_
_x000D_
<div class="wrapper" id="fsbar">_x000D_
<!-- Sidebar Holder -->_x000D_
<nav id="sidebar" :class="{ active: isActive }">_x000D_
<div class="sidebar-header">_x000D_
<h3>Bootstrap Sidebar</h3>_x000D_
<strong>BS</strong>_x000D_
</div>_x000D_
_x000D_
<ul class="list-unstyled components">_x000D_
<li class="active">_x000D_
<a href="#homeSubmenu" data-toggle="collapse" aria-expanded="false">_x000D_
<i class="glyphicon glyphicon-home"></i>_x000D_
Home_x000D_
</a>_x000D_
<ul class="collapse list-unstyled" id="homeSubmenu">_x000D_
<li><a href="#">Home 1</a></li>_x000D_
<li><a href="#">Home 2</a></li>_x000D_
<li><a href="#">Home 3</a></li>_x000D_
</ul>_x000D_
</li>_x000D_
<li>_x000D_
<a href="#">_x000D_
<i class="glyphicon glyphicon-briefcase"></i>_x000D_
About_x000D_
</a>_x000D_
<a href="#pageSubmenu" data-toggle="collapse" aria-expanded="false">_x000D_
<i class="glyphicon glyphicon-duplicate"></i>_x000D_
Pages_x000D_
</a>_x000D_
<ul class="collapse list-unstyled" id="pageSubmenu">_x000D_
<li><a href="#">Page 1</a></li>_x000D_
<li><a href="#">Page 2</a></li>_x000D_
<li><a href="#">Page 3</a></li>_x000D_
</ul>_x000D_
</li>_x000D_
<li>_x000D_
<a href="#">_x000D_
<i class="glyphicon glyphicon-link"></i>_x000D_
Portfolio_x000D_
</a>_x000D_
</li>_x000D_
<li>_x000D_
<a href="#">_x000D_
<i class="glyphicon glyphicon-paperclip"></i>_x000D_
FAQ_x000D_
isActive: false, </a>_x000D_
</li>_x000D_
<li>_x000D_
<a href="#">_x000D_
<i class="glyphicon glyphicon-send"></i>_x000D_
Contact_x000D_
</a>_x000D_
</li>_x000D_
</ul>_x000D_
_x000D_
<ul class="list-unstyled CTAs">_x000D_
<li><a href="https://bootstrapious.com/tutorial/files/sidebar.zip" class="download">Download source</a></li>_x000D_
<li><a href="https://bootstrapious.com/p/bootstrap-sidebar" class="article">Back to article</a></li>_x000D_
</ul>_x000D_
</nav>_x000D_
_x000D_
<!-- Page Content Holder -->_x000D_
<div id="content">_x000D_
_x000D_
<nav class="navbar navbar-default">_x000D_
<div class="container-fluid">_x000D_
_x000D_
<div class="navbar-header">_x000D_
<button type="button" id="sidebarCollapse" class="btn btn-info navbar-btn" @click="toggle()">_x000D_
<i class="glyphicon glyphicon-align-left"></i>_x000D_
<span>Toggle Sidebar</span>_x000D_
</button>_x000D_
</div>_x000D_
_x000D_
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">_x000D_
<ul class="nav navbar-nav navbar-right">_x000D_
<li><a href="#">Page</a></li>_x000D_
<li><a href="#">Page</a></li>_x000D_
<li><a href="#">Page</a></li>_x000D_
<li><a href="#">Page</a></li>_x000D_
</ul>_x000D_
</div>_x000D_
</div>_x000D_
</nav>_x000D_
_x000D_
<h2>Collapsible Sidebar Using Bootstrap 3</h2>_x000D_
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>_x000D_
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>_x000D_
_x000D_
<div class="line"></div>_x000D_
_x000D_
<h2>Lorem Ipsum Dolor</h2>_x000D_
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>_x000D_
_x000D_
<div class="line"></div>_x000D_
_x000D_
<h2>Lorem Ipsum Dolor</h2>_x000D_
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>_x000D_
_x000D_
<div class="line"></div>_x000D_
_x000D_
<h3>Lorem Ipsum Dolor</h3>_x000D_
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>_x000D_
</div>_x000D_
</div>_x000D_
_x000D_
_x000D_
_x000D_
_x000D_
_x000D_
<!-- jQuery CDN -->_x000D_
<script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>_x000D_
<!-- Bootstrap Js CDN -->_x000D_
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>_x000D_
_x000D_
/<script type="text/javascript">_x000D_
// $(document).ready(function () {_x000D_
// $('#sidebarCollapse').on('click', function () {_x000D_
// $('#sidebar').toggleClass('active');_x000D_
// });_x000D_
// }); jquery equivalent to vue_x000D_
</script>_x000D_
</body>_x000D_
</html>
_x000D_
This example is using Lists: When clicking in some li it turn red
html:
<div id="app">
<ul>
<li @click="activate(li.id)" :class="{ active : active_el == li.id }" v-for="li in lista">{{li.texto}}</li>
</ul>
</div>
JS:
var app = new Vue({
el:"#app",
data:{
lista:[{"id":"1","texto":"line 1"},{"id":"2","texto":"line 2"},{"id":"3","texto":"line 3"},{"id":"4","texto":"line 4"},{"id":"5","texto":"line 5"}],
active_el:0
},
methods:{
activate:function(el){
this.active_el = el;
}
}
});
css
ul > li:hover {
cursor:pointer;
}
.active {
color:red;
font-weight:bold;
}
Fiddle:
If you need more than 1 class
You can do this:
<i id="icon"
v-bind:class="{ 'fa fa-star': showStar }"
v-on:click="showStar = !showStar"
>
</i>
data: {
showStar: true
}
Notice the single quotes ' around the classes!
Thanks to everyone else's solutions.
If you don't need to access the toggle from outside the element, this code works without a data variable:
<a @click="e => e.target.classList.toggle('active')"></a>
In addition to NateW's answer, if you have hyphens in your css class name, you should wrap that class within (single) quotes:
<th
class="initial "
v-on:click="myFilter"
v-bind:class="{ 'is-active' : isActive}"
>
<span class="wkday">M</span>
</th>
See this topic for more on the subject.
Source: Stackoverflow.com