What are some creative ways to design the selected tab?

In my Vue parent component, I have multiple child components.

There are several elements that toggle between components by updating the current data.

The issue is that I am unsure how to indicate which tab is currently active.

I've tried various lifecycle hooks like updated, beforeupdated, mounted, created, and beforecreated, but none of them seem to work.

Currently, the code only applies styling to the initial tab (which is "Home"). I want it to highlight only the active tab without affecting others, but unfortunately, it doesn't work as intended.

Most of the time, it either styles all visited links, doesn't work at all, or only works for the initially active tab.

Here is a snippet of the important code from the parent component:


<template>
  <div id="grid">
    <nav id="navbar">

      <ul id="nav">
        <a href="#" class="Home" @click="current = 'Home'" ><li>{{navbar.Home}}</li></a>        
        <a href="#" class="Reservation" @click="current = 'Reservation'" ><li>{{navbar.Reservation}}</li></a>
        <a href="#" class="About-us" @click="current = 'About-us'" ><li>{{navbar.About}}</li></a>
        <a href="#" class="Contact" @click="current = 'Contact'" ><li>{{navbar.Contact}}</li></a>
      </ul>

      <div class="button"> 
        <a href="#">Sign Up
        </a>
      </div>
      <img src="https://i.pinimg.com/564x/8b/fa/5d/8bfa5d6a52a03e83b995fec69a4d8c2c.jpg" alt="" id="logo">
    </nav>      

    <main id="content"> 
      <keep-alive>
        <transition name="component-fade" mode="out-in">
          <component v-bind:is="current"></component>    
        </transition> 
      </keep-alive>          
    </main>      

    <footer>
      <p>Copyright © All Rights Reserved</p>
    </footer>
  </div>
</template>

<script>
import Home from "./components/Home.vue";
import Aboutus from "./components/About us.vue";
import Contact from "./components/Contact.vue";
import Reservation from "./components/Reservation.vue";
import Signup from "./components/Signup.vue";

export default {
  components: {
    Home: Home,
    "About-us": Aboutus,
    Contact: Contact,
    Reservation: Reservation,
    Signup: Signup
  },
  data() {
    return {
      navbar: {
        Home: "Home",
        Reservation: "Reservation",
        About: "About us",
        Contact: "Contact"
      },
      current: "Home"
    };
  },
  mounted: function() {
    let activeTab = document.querySelector("." + this.current);
    activeTab.className = "active";
  },
  beforeUpdate: function() {
    let previousTab = document.querySelector("." + this.current);
    previousTab.className = "none";
  },
  methods: {}
};    

</script>

Answer №1

While I'm not a Vuejs expert, I found an example on the vuejs.org website that may be relevant to what you're looking for in terms of CSS styles.

You can view the sample here: https://v2.vuejs.org/v2/guide/components.html#Dynamic-Components

I hope this information is helpful

<h2 id="Dynamic-Components"><a href="#Dynamic-Components" class="headerlink" title="Dynamic Components"></a>Dynamic Components</h2><p>There are times when dynamically switching between components, such as in a tabbed interface, can be beneficial:</p>

<div id="dynamic-component-demo" class="demo">
  <button v-for="tab in tabs" v-bind:key="tab" class="dynamic-component-demo-tab-button" v-bind:class="{ 'dynamic-component-demo-tab-button-active': tab === currentTab }" v-on:click="currentTab = tab">
    {{ tab }}
  </button>
  <component v-bind:is="currentTabComponent" class="dynamic-component-demo-tab"></component>
</div>
<script>
Vue.component('tab-home', { template: '<div>Home component</div>' })
Vue.component('tab-posts', { template: '<div>Posts component</div>' })
Vue.component('tab-archive', { template: '<div>Archive component</div>' })
new Vue({
  el: '#dynamic-component-demo',
  data: {
    currentTab: 'Home',
    tabs: ['Home', 'Posts', 'Archive']
  },
  computed: {
    currentTabComponent: function () {
      return 'tab-' + this.currentTab.toLowerCase()
    }
  }
})
</script>
<style>
.dynamic-component-demo-tab-button {
  padding: 6px 10px;
  border-top-left-radius: 3px;
  border-top-right-radius: 3px;
  border: 1px solid #ccc;
  cursor: pointer;
  background: #f0f0f0;
  margin-bottom: -1px;
  margin-right: -1px;
}
.dynamic-component-demo-tab-button:hover {
  background: #e0e0e0;
}
.dynamic-component-demo-tab-button-active {
  background: #e0e0e0;
}
.dynamic-component-demo-tab {
  border: 1px solid #ccc;
  padding: 10px;
}
</style>

Answer №2

Everything is functioning as expected. The issue arises when you manipulate the DOM directly, without Vue being aware of it. Vue operates on its own virtual DOM, so it's important to handle changes appropriately. You can follow this example or explore more about dynamic class binding in the Vue guide:

<ul id="nav">
  <a
    href="#"
    class="['Home', current === 'Home' ? 'active' : '']"
    @click="current = 'Home'"
  >
    <li>{{navbar.Home}}</li>
  </a>        
  <a
    href="#"
    class="['Reservation', current === 'Reservation' ? 'active' : '']"
    @click="current = 'Reservation'"
  >
    <li>{{navbar.Reservation}}</li>
  </a>
  <a
    href="#"
    class="['About-us, current === 'About-us' ? 'active' : '']"
    @click="current = 'About-us'"
  >
    <li>{{navbar.About}}</li>
  </a>
  <a
    href="#"
    class="['Contact', current === 'Home' ? 'active' : '']"
    @click="current = 'Contact'"
  >
    <li>{{navbar.Contact}}</li>
  </a>
</ul>

Consider removing the mounted and beforeUpdate hooks...

Note: It is recommended to use button elements for navigation to enhance semantics and accessibility. It is now considered deprecated/antipattern to use a within li tags.

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

Where should the webapp files for a Node.js application be located within the server directory?

Can someone help clarify a question I have been struggling with? I have created a nodejs webapp with a specific directory structure, as shown in the screenshot. This app will eventually incorporate MongoDB and store a large number of audio files. I am usi ...

Unable to populate an array with a JSON object using Angular framework

Here is the JSON object I have: Object { JP: "JAPAN", PAK: "PAKISTAN", IND: "INDIA", AUS: "AUSTRALIA" } This JSON data was retrieved as a response from an HTTP GET request using HttpClient in Angular. Now, I want to populate this data into the following ...

Why is the imported package not being recognized in the namespace declaration of my Node.js TypeScript file?

Currently, I am utilizing the WebStorm IDE developed by JetBrains to modify a TypeScript file within a Node.js v8.6.0 project. The JavaScript version set for this project is JSX Harmony. In the beginning of the TypeScript source file, there is an import st ...

Unveiling the hidden secrets of HTML code through scraping

Looking to extract data from the cadastral records in Poland available at . Specifically, I am interested in retrieving information from the element tagged with id 'gfi_0'. The challenge is that this element is not immediately accessible; it only ...

Utilize the get method to showcase data in a material UI table for a React application

Just starting out with React. Managed to create a table component with hard-coded data. However, I now have all the data stored in table.json. Can someone guide me on how to fetch values from table.json using an axios get request an ...

What is the difference in memory usage for JavaScript objects between Node.js and Chrome?

It's puzzling to me why the size of the heap is twice as large as expected. I meticulously constructed a binary tree with perfection. I suspect v8 recognizes that each node consists of 3 fields. function buildTree(depth) { if (depth === 0) return n ...

Determining the Nearest Form to an Element using jQuery

I developed a JavaScript/jQuery script that allows me to check all checkboxes within a form. The function works effectively, but the issue is that it checks all checkboxes on the page regardless of their form wrapper. Here is the function: function toggl ...

Writing a CSV file to AWS S3 proves to be unsuccessful

I have been working with TypeScript code that successfully writes a CSV file to AWS S3 when running locally. However, I have recently encountered an error message: s3 upload error unsupported body payload object NOTES: The code is not passing creden ...

Creating a Mongoose schema to store an array of objects, where updates will automatically add new objects

const mongoose = require('mongoose'); module.exports = mongoose.model('GridModel', { Request_Id : { type : Number, required : true }, viewStudents : { type : Array , default : [] } }); The mongoose model above needs to b ...

In Chrome, CSS automatic hyphens are displayed as question mark symbols

On my website, I have implemented automatic hyphenation using CSS: article > p, article > li { -o-hyphens: auto; -o-hyphenate-limit-before: 3; -o-hyphenate-limit-after: 3; -o-hyphenate-limit-chars: 6 3 3; -o-hyphenate-limit-lines: 2; -o-h ...

"When attempting to pass a string into the res.send() method in Node.js, undefined

As a new Node.js user, I'm attempting to send data back to the browser by utilizing a function called load_blocks() from an external file that I created, and then calling it with res.send(). I currently have two basic files in my setup: The first on ...

Using both Promise based architecture and events in Node.js can lead to unexpected behavior and should be avoided

Currently, I am developing a nodejs application that is expected to grow in size. Despite my efforts, I have not been able to find many resources on advanced Nodejs project architecture and structure. I am wondering if it would be considered bad practice ...

What is the best method for verifying that audio has not been loaded correctly?

After creating a script to scrape for mp3 audio file URLs and load them into my HTML audio element's src, I encountered an issue where some of the URLs were not functioning properly. As a result, the audio was unable to execute the load() method since ...

How to refresh component after clearing dates in Vuetify datepicker

Currently, I am working with a datepicker in Vuetify JS and I need to find a way to clear the dates and refresh the component. In addition, there is a v-data table that is filtered based on the dates range array. I am exploring options to either add a &ap ...

Retrieve an array from the updated scope

I need help with my code. How can I retrieve the names from an array and display them in my input box? Also, how do I get all the changed names back into the array? Thanks in advance! - Marco app.js var g[]; var names = ['John', 'Steve&apo ...

The content has spilled over from the div and leaked into the adjacent div

When the left div's content exceeds the right div's, it spills over into the next container div. Sample HTML: <div class="musictemplate_container"> <div class="musictemplate_left"> something<br> omething< ...

The autoIncrement feature is causing a syntax error at or near "SERIAL"

Encountering a build error : Unable to start server due to the following SequelizeDatabaseError: syntax error at or near "SERIAL" This issue arises only when using the autoIncrement=true parameter for the primary key. 'use strict'; export ...

Tips for seamlessly incorporating WalletConnect into your decentralized app with the help of web3-react

I have been working on integrating WalletConnect into my project by referring to the documentation provided by web3-react. The configuration settings I am using for the connector are as follows: import { WalletConnectConnector } from '@web3-react/wal ...

JSdom, automation, web scraping, handling dynamic iframes

I am currently in the process of automating my tasks on the website provided at the link below: I need to fill out forms and submit them automatically. So far, I have been successful in automating using Greasemonkey and I am now considering switching to ...

Leveraging Vuejs 2 with VUEX for seamless data-binding during data editing

I am currently facing an issue with my user profile section's edit functionality. I am using vuex to store the user profile data and retrieving it into the form. The edit form is nested in a child component of userProfile, where the data gets loaded a ...