Vuejs tutorial: Toggle a collapsible menu based on the active tab status

I am using two methods called forceOpenSettings() and forceCloseSettings() to control the opening and closing of a collapsible section. These methods function properly when tested individually. However, I need them to be triggered based on a specific condition related to a b-tab with 4 tabs. When a tab is clicked, the collapse should open and when it becomes inactive, the collapse should close.

<b-tabs content-class="mt-3">
  <b-tab title="First" active><p>I'm the first tab</p></b-tab>
  <b-tab title="Second"><p>I'm the second tab</p></b-tab>
</b-tabs>

I have successfully implemented a similar functionality using @show and @hide in a b-collapse element.

<b-collapse role="tabpanel" @show="forceOpenSettings" @hide="forceCloseSettings">......</b-collapse>

Answer №1

JavaScript Vanilla: An example of a Dynamic iterator that checks for the presence of the 'active' attribute...

function opendiv() {
  document.getElementById('myDiv').style.display = "block";
}

function closediv() {
  document.getElementById('myDiv').style.display = "none";
}

let tabs = document.getElementsByTagName('b-tab');
for (let i = 0; i < tabs.length; i++) {
  tabs[i].addEventListener('click', event => {
    if (tabs[i].getAttribute("active") !== null) {
      opendiv();
    } else {
      closediv();
    }
  });
}
<b-tabs content-class="mt-3">
  <b-tab title="First">
    <p>I'm the first tab</p>
  </b-tab>
  <b-tab title="Second" active>
    <p>I'm the second tab</p>
  </b-tab>
</b-tabs>

<div id="myDiv" style="display:none;">Show this div when second tab has an attribute named 'active'</div>

Retrieve elements by their tag name... Then create a conditional statement to look for the second instance of the elements using the index 1, which corresponds to the second tab. Verify whether the attribute is not set to null, indicating it is present but empty. If the attribute is absent, the function will return null.

  let tabs = document.getElementsByTagName('b-tab');

  if(tabs[1].getAttribute("active") !== null){
    // execute opendiv();
  }else{
    // execute closediv();
  }

Answer №2

With Vue, the data drives everything, eliminating the need for functions like this:

{
  ...,
  data(){
    return {
      ...,
      active: 'first',
      tabs: ["first", "second", "third"]
    }
  }
}
<b-tabs content-class="mt-3">
  <b-tab
    v-for="tab in tabs"
    :key="tab"
    :title="tab" 
    :active="active==tab" 
    @click="active=tab" 
    :style="`display:${active==tab? 'block':'none}`'"
  >
    <p>I'm the {{tab}} tab</p>
  </b-tab>

</b-tabs>

Incorporating interaction with b-collapse component

{
  props: ["tab", "active"],
  computed(){
    collapse: {
      get: function(){
        return this.active == this.tab
      },
      set: function(value){
        this.$emit('update:active', this.tab)
      }
    }
  }
}
<!-- Encapsulate in a component for proper prop management -> no collapse[tab] needed than -->
<template>
<b-collapse 
  role="tabpanel" 
  v-model="collapse"
 ><slot></slot></b-collapse>
 </template>

 <!-- within the scope of tabs -->
 <wrapped-collapse 
    v-for="tab in tabs"
    :key="tab"
    :active.sync="active" :tab="tab"  
  >...</wrapped-collapse>

Answer №3

There is a simple way to achieve this without using multiple functions.

All you need is one function that removes the active attribute from all tabs and then adds it to the tab you clicked on. Just assign the class tab to all your <b-tab> elements, and you can apply this single function to any tab with that class. Trigger the function using the @click="doTabs()" directive.

The updated answer pertains to utilizing a Vue instance.

Execute the snippet below to observe the functionality.

new Vue({
  el: '#app',
  methods: {
    doTabs() {
      const tabs = document.querySelectorAll('.tab')
      tabs.forEach(i => i.removeAttribute('active'))
      event.currentTarget.setAttribute('active', true)
    }
  }
})
.tab {padding: 10px; border: 1px solid #ccc; cursor: pointer; display: flex; display: block}
[active] {background-color: #eee}
.content {padding-left: 20px; font-size: 12px; visibility: hidden; opacity: 0; transition: all 0.2s ease; margin-top: -40px}
[active] .content {visibility: visible; opacity: 1;margin-top: 0}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <div title="First" class="tab" @click="doTabs()" active>
    <p>I'm the first tab</p>
    <div class="content">
      <p>Here is all the<br>accordion content</p>
    </div>
  </div>
  <div title="Second" class="tab" @click="doTabs()">
    <p>I'm the second tab</p>
    <div class="content">
      <p>Here is all the<br>accordion content</p>
    </div>
  </div>
</div>

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

What is the reason behind the perpetual hiding of the button?

<div class="app__land-bottom" v-if="isVisible"> <a href="#projects"> <img ref="arrowRef" id="arrow" src="./../assets/down.png" alt srcset /> </a> </div> When ...

deleting the current product information during an ajax request

After executing the query provided below, I have $product_list in this code. However, I want to use ajax so that when I click on the button link1, $product_list gets emptied. How can I clear the content within products_list using an ajax call triggered by ...

Enable users to provide ratings ranging from 0.5 up to 5

I recently created a rating component that allows users to rate on a scale from 0 to 4.5, with increments of 0.5, which is causing unexpected behavior. I actually want users to be able to rate from 0.5 to 5 instead. How can I achieve this adjustment? Below ...

Asynchronous waterfall call in Node.js to call the method before

Is it possible to invoke a previous method within async.waterfall from a subsequent method? async.waterfall([ function (callback) { }, function (reservationStatus, callback) { }, function (reservationStatusList, f ...

I attempted to make changes to a Firebase document using the update() function, however, the document did not reflect

I am currently in the process of creating a blog and have been focusing on implementing an edit post feature. However, I have encountered an issue where when I utilize the ref.update() method, it indicates that the update was successful but I do not see an ...

Guide to deploying a complete Wordpress application within a Nuxt application

Is it feasible to integrate a complete WordPress application into a Nuxt app? Specifically, I want my app's address to be foo.com, with the WordPress app accessible at foo.com/bar. Can this be achieved, and will the Nuxt router be able to manage this ...

Troubleshooting Angular 2: Instances of Classes Not Being Updated When Retrieving Parameters

I am facing an issue with the following code snippet: testFunction() { let params = <any>{}; if (this.searchTerm) { params.search = this.searchTerm; } // change the URL this.router.navigate(['job-search'], {q ...

What role does a promise play in rendering code asynchronous?

While we often use promises to avoid the dreaded function callback hell, a question remains: where exactly in the event loop does the promise code execute and is it truly asynchronous? Does the mere fact that the code is within a promise make it asynchron ...

Angular-Translate fails to function within a tag's attribute

For my project, I utilize angular-translate. One of the key definitions looks like this: { "paging":{ "first":"First", "last":"Last", "next":"Next2", "pre":"Previous" } } I implement it in the following way: <uib-pagination first-tex ...

Step-by-step guide on retrieving data from E-goi with REST API in Google Apps Script

Looking to extract data from the e-goi API, I found a .jar file in their documentation. Unfortunately, there are no examples provided for the REST API, leaving me unsure of how to access it directly. As I'm still new to programs like this, I could rea ...

Storing Firestore Timestamp as a Map in the database

Snippet Below const start = new Date(this.date + 'T' + this.time); console.log(start); // Thu Sep 12 2019 04:00:00 GMT+0200 const tournament:Tournament = { start: firebase.firestore.Timestamp.fromDate(start) } When passing the tournament ...

Tips for sending information from PHP to an AJAX function

Hello, I am in the process of learning PHP and I am attempting to retrieve data from a PHP file using the script below. However, I am not receiving any response: $.ajax({ type: 'POST', url: "mark_mod.php", ...

Fixing PNG Fading Issue in Internet Explorer 8

I am currently utilizing the jQuery Cycle plugin to produce a fading animation effect. While this works perfectly on most browsers, I have encountered an issue with PNG files containing semi-transparent pixels in Internet Explorer 8. These partially transp ...

Combining Data in Django using Ajax with JavaScript and Python Integration

I am in need of assistance understanding a basic ajax call from JavaScript to Python. I have a Python function that takes a simple parameter and returns a result. My goal is to send this parameter from JavaScript, receive the function result back in JavaSc ...

Configure WebStorm so that node_modules is set as the library root, while simultaneously excluding it from indexing

Can WebStorm projects be configured to set the node_modules as the library root, while also excluding it from indexing? I thought I saw a project that had node_modules marked as both library root and excluded, but I'm unsure how to do this. Does anyo ...

Utilizing Typescript Generics in Arrow Function to Combine Two Arguments

For instance, I am working with this code in a .tsx file extension const Add = <T,>(arg0: T, arg1: T): T => arg0 + arg1; const A = Add(1, 2); const B = Add('1', '2') However, I am encountering an issue, as there is an error m ...

What is the best way to use res.sendFile() to serve a file from a separate directory in an Express.js web application?

I have a situation within the controllers folder: //controler.js exports.serve_sitemap = (req, res) => { res.sendFile("../../sitemap.xml"); // or // res.send(__dirname + "./sitemap.xml") // But both options are not working }; ...

Organize information received from a post request into a JSON template

I am attempting to automatically sort information from a post request. Each category is identified by a number (0 -> 1 -> ....) There is one title defined for each category with its respective number, for example: "0": "Are planes fly ...

Show or hide the right element when clicked using ng-show in AngularJS

My goal is to toggle elements based on which one is clicked, not all at once. For instance, if I have 3 form elements and 3 buttons, when I click on button 1, I only want to toggle the corresponding form element. Here is my current code snippet: In Angu ...

Including an <a> tag within a JavaScript variable to utilize in an HTML statement

I want to wrap an <a> element around a JavaScript variable containing a string. The desired output should be the 'copyright symbol' followed by the 'companyName' linked as an HTML link and then the current year's date. JavaS ...