Applying an active class in VueJs to a specific li element within a v-for loop when clicked

Struggling to select (set active class) in a v-for loop when one class is already selected. Here's the code and an explanation:

These are my available subscriptions, with one 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>

JS code snippet:

checkIfClassActive(userSubscriptionKey) {
    if (userSubscriptionKey === this.userSubscription.subscription_key) {
        return 'active';
    }
},
setActive(key, index) {

},

Displayed image: https://i.stack.imgur.com/fLZWt.png

My dilemma lies in properly implementing the setActive function - upon clicking a li element, it should become active while all others lose the active class. Can you assist me in solving this issue?

If more information is needed, please let me know. Thank you!

Answer №1

Include a new property in your code named activeIndex:

  data() {
    return {
      activeIndex: undefined
    }
  },

Also, implement the 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);

    }
  }

Make some changes to your template as well:

<ul>
    <li v-for="(s, index) in subscriptions"
        :class="{ 'active': activeIndex === index }" :key="s.id"
        @click="setActive(s, index)">
        {{ s.name }}
    </li>
</ul>

The idea is to specify which index should be considered active by setting the activeIndex property. The active CSS class will be applied to the list element with an index matching the activeIndex.

If you want to set activeIndex to the existing choice before the user makes any changes, you can do so by assigning the current subscription of the user to activeIndex while fetching subscription data.

See it in action here: http://jsfiddle.net/eywraw8t/256701/

Answer №2

Update the

this.userSubscription.subscription_key
variable each time a tab is selected. Use setActive(s.subscription_key) to achieve this functionality. Here's an example of how you can implement it:

<li v-for="(s, key, index) in subscriptions"
        :class="checkIfClassActive(s.subscription_key)"
        @click="setActive(s.subscription_key)">
        {{ s.name }}
</li>

JavaScript:

checkIfClassActive(userSubscriptionKey) {
    if (userSubscriptionKey === this.userSubscription.subscription_key) {
        return 'active';
    }
},
setActive(subscription_key) {
    this.userSubscription.subscription_key=subscription_key;
},

Answer №3

Here is a basic example demonstrating the process:

Example of HTML code:

<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 logic section:

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 proceed further
      this.items.find(item => item.id === this.previous_active_id).class = '' //deactivate the previously active list item
      this.items.find(item => item.id === id).class = 'active' //activate the new list item
      this.previous_active_id = id //update the ID of the newly active list item
    }
  }
})

View it live

Answer №4

this is a quick example

when utilizing 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 initial load and current path
                        }
                    },
                    computed: {
                        cats() {
                            ...
                        }
                    },
                    methods: {
                        itemActive(e) {
                            this.itemA = e;
                        }
                    },

                }
            </script>

            <style>
                .active {
                    ...
                }
            </style>

if you do not require v-for and want to use router-link within an 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>

Answer №5

If you're facing this issue, a simple solution would be to replace the "li" tags with "router-link", and then adjust the default styling of the router-link. In particular, focus on the "router-link-active" class.

<ul>
   <router-link v-for="item in items"
     :key="item.id"
     :to="item.route"
    >
        {{ s.name }}
      </router-link>
   </ul>


 <style>
   .router-link-active{
     ...
   }
 </style>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Show only specific data from JSON results

I am trying to display a specific cryptocurrency's price without the need for curly braces or explicitly stating "USD". Currently, it appears as {"USD":0.4823} when using the following code: <script> $(document).ready(function () { ...

Ensuring consistent placement and scrollability of two divs across all screen sizes

I am in need of a solution to fix the top and bottom divs in the given image. The scroll should only occur when there is overflow. <!DOCTYPE html> <html> <head> <script src="//code.jquery.com/jquery-1.9.1.min.js"></script> ...

What is the process for sending a message from the internet to a mobile device?

We are currently in the process of developing a website that sends SMS alerts to users for specific services, however I am struggling to set up a script that can perform this function. If anyone has any suggestions or recommendations for a solution, pleas ...

What is causing the ajax code to malfunction?

I am new to ASP MVC and trying to create a login form using AJAX. I have written a JsonResult in the controller to check the username and password, but for some reason it is not working. Here is my controller code: public ActionResult login() { ...

Steps for importing JQuery into a custom DNN module

I have developed a custom DNN module that requires the use of certain JQuery plugins. I successfully loaded the plugins, but encountered the following error: Uncaught TypeError: undefined is not a function imagesloaded.js?cdv=18:93 Uncaught TypeError: ...

Guide on decrypting a file encrypted with C# using Node JS

I currently have encrypted files in C# using DES and PKCS7 encryption. My objective is to decrypt these files in Node JS. The decryption code in C# that I am using appears like this: public string SSFile_Reader( string fileToDecrypt ) { DESCryptoService ...

Form submission requires a checkbox to be checked

I have been searching for a way to make checkboxes required. Is there a method similar to using required="required"? Currently, I generate my checkboxes in the following manner and would really appreciate any guidance on this topic. It's crucial for m ...

What is the best way to pre-fetch data using axios in Vue?

My app requires offline functionality for drivers operating in remote areas with limited internet access. To address this, I aim to pre-download all necessary data using Axios requests when an internet connection is available. This way, the app can retriev ...

Designing a versatile pop-up window with jQuery or JavaScript that functions seamlessly across all web browsers

I've encountered an issue with my code where it displays a popup message correctly in Chrome, but when testing it on Firefox and Edge, it creates a strange box at the end of the page instead. Here is the code snippet I'm referring to: var iframe ...

sending functions into angular as opposed to using 'function()'

Lately, I've been immersing myself in Angular development. One thing that caught my interest was the idea of using a declared function instead of a generic "function() {}" placeholder, particularly in scenarios like handling promise callbacks. I encou ...

Tips on allowing the backend file (app.js) to handle any URL sent from the frontend

In my Express app, I have two files located in the root directory: index.js and index.html. Additionally, there is a folder named "server" which contains a file named app.js that listens on port 3000. When running index.html using Live Server on port 5500 ...

"Trouble with kendo drop-down list: onclick event not triggering when text is changed

I am currently working with kendo UI and have implemented a dropdown list of checkboxes. The onchange event is triggering when the user clicks on the checkbox, but it is not firing when the user clicks on the text. Thank you in advance for your assistance ...

What is the best way to display a progress bar as a percentage?

Is there a way to visually represent the progress of an upload on the screen using percentages? I want to display a bar that starts at 0% and updates with the percentage from the percentComplete variable. Once the upload is finished, I'd like to show ...

`How can I activate caching for getServerSideProps in Next.js?`

We have implemented server-side rendering for a few pages and components. In an attempt to optimize performance, we have been experimenting with caching API responses. export async function getServerSideProps(context) { const res = await getRequest(API ...

Encountering a CORS policy issue while attempting to retrieve data from an API

I have been attempting to retrieve data from the DHL API, however, I keep encountering issues due to CORS policy blocking the request. Even though I have configured the CORS policy on my backend server, the error persists. What could be the issue? Here ...

Learn how to insert JavaScript code into the head of an iframe using jQuery

My goal is to inject javascript code into the head of an iframe using jquery with the code provided below. var snippets_js='<?php echo $snippets_javascript;?>'; var scriptjs = document.createElement("script"); scriptjs.type = "text/j ...

Developing a Vue.js API integration

I am struggling to understand why my code is not working as expected. My goal is to retrieve photos from a random dogs API, but something seems to be going wrong. Take a look at the code below. export default { data() { return { posts: [], ...

Experiencing challenges during the creation of a NUXT build

Trying to build a Nuxt SSR app, but encountering an error related to the css-loader during the build command execution. The issue seems to be with Invalid options object. ERROR in ./node_modules/vue2-google-maps/dist/components/streetViewPanorama.vue (./no ...

I am looking to modify various attributes linked to Rails

My Desire for Reality I am looking to update multiple related values in Rails by sending an update request from JavaScript. While creating data was seamless, I encountered difficulties when attempting to update it. #Code JavaScript* export const actions ...

Ways to incorporate radio buttons, checkboxes, and select fields into a multi-step form using JavaScript

In the snippet below, I have created a multi-step form where users can provide details. The issue is that currently only text input fields are being accepted. The array of questions specifies the type of input required for each question: Question no.1 req ...