[css] Vue.js toggle class on click

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.

This question is related to css vue.js

The answer is


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:

_x000D_
_x000D_
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_
_x000D_
_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
}

_x000D_
_x000D_
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_
_x000D_
_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:

https://jsfiddle.net/w37vLL68/158/


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.