Giacomo Ciampoli
Giacomo Ciampoli

Reputation: 821

toggle active class on list menu items - vue js

I want that, clicking on a menu item, the active class is triggered only for that specific item and removed for the others, until now I wrote this:

<template>
  <nav class="navbar">
    <div class="navbar__brand">
      <router-link to="/">Stock Trader</router-link>
    </div>
    <div class="navbar__menu">
      <ul class="navbar__menu--list">
        <li @click="isActive=!isActive" class="navbar__menu--item" :class="{active:isActive}">
          <router-link to="/portfolio">Portfolio</router-link>
        </li>
        <li @click="isActive=!isActive" class="navbar__menu--item" :class="{active:isActive}">
          <router-link to="/stocks">Stocks</router-link>
        </li>
      </ul>
    </div>
    <div class="navbar__menu--second">
      <ul class="navbar__menu--list">
        <li @click="isActive=!isActive" class="navbar__menu--item" :class="{active:isActive}">
          <a href="#">End Day</a>
        </li>
        <li @click="isActive=!isActive" class="navbar__menu--item" :class="{active:isActive}">
          <a href="#">Save / Load</a>
        </li>
      </ul>
    </div>
  </nav>
</template>
<script>

    export default {
      data(){
        return{
          isActive: false

        }
      }
    }
</script>

now of course, when I click on one item the active class is inserted/removed for all the items, what is the best solution for making that only a specific item, on clicking on it, receives the active class?

Upvotes: 1

Views: 9310

Answers (5)

Rashiqul Rony
Rashiqul Rony

Reputation: 89

Here is custom menu active no dynamic menus. This working like Laravel

       <li class="sidebar-dropdown" :class="$route.name === 'CategoryEdit' || $route.name === 'CategoryCreate' || $route.name === 'Categories' ? 'active' : ''">
          <a><i class="fa fa-cubes"></i> <span>Categories</span></a>
          <div class="sidebar-submenu" :class="$route.name === 'CategoryEdit' || $route.name === 'CategoryCreate' || $route.name === 'Categories' ? 'd-block' : ''">
            <ul>
              <li :class="$route.name === 'Categories' ? 'subactive' : ''">
                <router-link :to="{name: 'Categories'}">List</router-link>
              </li>
              <li :class="$route.name === 'CategoryCreate' ? 'subactive' : ''">
                <router-link :to="{name: 'CategoryCreate'}">Create</router-link>
              </li>
            </ul>
          </div>
        </li>

Upvotes: 0

Fl0-dev
Fl0-dev

Reputation: 41

If you have several ul => use title instead of index. For example :

<ul>
                <div>
                    Applicants
                </div>
                <li
                    v-for="(title, index) in applicantMenuTitles"
                    :key="index"
                    :class="{ active: active === title }"
                    @click="updateActive(title)"
                >
                    {{ title }}
                    <div
                        v-if=" active === title "
                        class="cursor"
                    />
                </li>
            </ul>
            <ul>
                <div>
                    Offices
                </div>
                <li
                    v-for="(title, index) in officeMenuTitles"
                    :key="index"
                    :class="{ active: active === title }"
                    @click="updateActive(title)"
                >
                    {{ title }}
                    <div
                        v-if=" active === title "
                        class="cursor"
                    />
                </li>
            </ul>
And on script :

...
const active = ref('')

function updateActive(title: string) {
    active.value = title
}

Upvotes: 0

Q10Viking
Q10Viking

Reputation: 1111

I do this in vue3. the template is:

<li
  v-for="(title, index) in titles"
  class="title"
  :key="index"
  :class="{ active: active === index }"
  @click="updateActive(index)"
>
   {{ title }}
</li>

and the script is

<script lang="ts" setup>
import { ref } from "vue"
const titles = ["title1","title2","title3"]
const active = ref(-1)

function updateActive(val: number) {
  active.value = val
}
</script>

Upvotes: 0

Toomean
Toomean

Reputation: 246

You could keep an object of links you have and handle a click on each of items. E.g.

data() {
  return {
    links: [
      {
        title    : 'Portfolio',
        to       : '/portfolio',
        isActive : false,
        location : 'first',
      },
      {
        title    : 'Stocks',
        to       : '/stocks',
        isActive : false,
        location : 'first',
      },
      {
        title    : 'End Day',
        to       : '#',
        isActive : false,
        location : 'second',
      },
      {
        title    : 'Save / Load',
        to       : '#',
        isActive : false,
        location : 'second',
      },
    ]
  };
},
methods: {
  handleNavClick(item) {
    this.links.forEach(el, () => {
      el.isActive = false;
    });

    item.isActive = true;
  }
},

Upvotes: 3

Phil
Phil

Reputation: 164729

You'll want some sort of identifier for each clickable item and set that to your data property. For example

data() {
  return { active: null }
}

and in your list items (for example)

<li @click="active = 'portfolio'"
    class="navbar__menu--item" 
    :class="{active:active === 'portfolio'}">

In this example, the identifier is "portfolio" but this could be anything, as long as you use a unique value per item.

Upvotes: 6

Related Questions