Bootstrap Tabs Vanilla JS shown event not working - javascript

I am trying to detect when a tab is shown through Vanilla JS and the event isn't working. I have looked through multiple questions about this and none of them seem to help. Here is my current code.
var aTabs = document.querySelectorAll('a[data-toggle="tab"');
console.log(aTabs);
for (let i = 0; i < aTabs.length; i++) {
console.log(aTabs[i].id);
aTabs[i].addEventListener('shown.bs.tab', function(e) {
console.log("Showing content for tab: " + e.target.href);
}, false);
}
<ul class="nav nav-tabs" id="tab-navigation" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="1link" data-toggle="tab" href="#1" role="tab" aria-controls="community" aria-selected="true">1 <span class="badge badge-primary"></span></a>
</li>
<li class="nav-item">
<a class="nav-link disabled" id="2link" data-toggle="tab" href="#2" role="tab" aria-controls="2" aria-selected="false">2 <span class="badge badge-primary"></span></a>
</li>
<li class="nav-item">
<a class="nav-link disabled" id="3link" data-toggle="tab" href="#3" role="tab" aria-controls="3" aria-selected="false">3 <span class="badge badge-primary"></span></a>
</li>
<li class="nav-item">
<a class="nav-link disabled" id="4link" data-toggle="tab" href="#4" role="tab" aria-controls="4" aria-selected="false">4 <span class="badge badge-primary"></span></a>
</li>
</ul>
<div class="tab-content" id="tab-navigation-content">
<div class="tab-pane fade show active" id="1" role="tabpanel" aria-labelledby="tab1"></div>
<div class="tab-pane fade" id="2" role="tabpanel" aria-labelledby="tab2"></div>
<div class="tab-pane fade" id="3" role="tabpanel" aria-labelledby="tab3"></div>
<div class="tab-pane fade" id="4" role="tabpanel" aria-labelledby="tab4"></div>
</div>
I have the console logs to make sure I am getting all the correct values and those are correct however the addEventListener isn't adding the event. When I click through tabs they do not trigger.
All the console logs show the correct elements, just the event isn't fired when switching between tabs.

According to this Stack Overflow post, you cannot use ".addEventListener" for custom jQuery events (e.g. "shown.bs.tab").
I cannot say why the jQuery ".on" version wouldn't work, though.

Your AddEventListener was wrong, as you weren't telling it what event you wanted to listen too. If you wanted to listen to the tab selection you should pass the click event handler.
Here is a JSFiddle as a sample http://jsfiddle.net/97nq823z/
var aTabs = document.querySelectorAll('a[data-toggle="tab"');
console.log(aTabs);
for (let i = 0; i < aTabs.length; i++) {
console.log(aTabs[i].id);
aTabs[i].addEventListener('click', writeToConsole(aTabs[i]));
}
function writeToConsole(tab) {
console.log(tab);
}
<ul class="nav nav-tabs" id="tab-navigation" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="1link" data-toggle="tab" href="#1" role="tab" aria-controls="community" aria-selected="true">1 <span class="badge badge-primary"></span></a>
</li>
<li class="nav-item">
<a class="nav-link disabled" id="2link" data-toggle="tab" href="#2" role="tab" aria-controls="2" aria-selected="false">2 <span class="badge badge-primary"></span></a>
</li>
<li class="nav-item">
<a class="nav-link disabled" id="3link" data-toggle="tab" href="#3" role="tab" aria-controls="3" aria-selected="false">3 <span class="badge badge-primary"></span></a>
</li>
<li class="nav-item">
<a class="nav-link disabled" id="4link" data-toggle="tab" href="#4" role="tab" aria-controls="4" aria-selected="false">4 <span class="badge badge-primary"></span></a>
</li>
</ul>
<div class="tab-content" id="tab-navigation-content">
<div class="tab-pane fade show active" id="1" role="tabpanel" aria-labelledby="tab1"></div>
<div class="tab-pane fade" id="2" role="tabpanel" aria-labelledby="tab2"></div>
<div class="tab-pane fade" id="3" role="tabpanel" aria-labelledby="tab3"></div>
<div class="tab-pane fade" id="4" role="tabpanel" aria-labelledby="tab4"></div>
</div>

Related

My content is not showing whenever I select the other option from nav-tab

<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="home-tab" data-bs-toggle="tab" data-bs-target="#home" type="button" role="tab" aria-controls="home" aria-selected="true">Home</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="profile-tab" data-bs-toggle="tab" data-bs-target="#profile" type="button" role="tab" aria-controls="profile" aria-selected="false">Profile</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="contact-tab" data-bs-toggle="tab" data-bs-target="#contact" type="button" role="tab" aria-controls="contact" aria-selected="false">Contact</button>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">This is home text</div>
<div class="tab-pane fade" id="profile" role="tabpanel" aria-labelledby="profile-tab">This is profile text</div>
<div class="tab-pane fade" id="contact" role="tabpanel" aria-labelledby="contact-tab">This is contact text</div>
</div>
Please check the code and guide me what I am doing wrong? Whenever I select the tab from nav-tab. My contact is not changing.

How to get the activated tab?

With bootstrap 5, I was never able to get the activated tab. according to their website I just get the ID of the first button, not the activated tab and nothing else.
var tabEl = document.querySelector('button[data-bs-toggle="tab"]')
tabEl.addEventListener('shown.bs.tab', function (event) {
alert(event.target.id) // newly activated tab
// event.relatedTarget // previous active tab
})
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.1/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.1/dist/js/bootstrap.bundle.min.js"></script>
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="home-tab" data-bs-toggle="tab" data-bs-target="#home" type="button" role="tab" aria-controls="home" aria-selected="true">Home</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="profile-tab" data-bs-toggle="tab" data-bs-target="#profile" type="button" role="tab" aria-controls="profile" aria-selected="false">Profile</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="contact-tab" data-bs-toggle="tab" data-bs-target="#contact" type="button" role="tab" aria-controls="contact" aria-selected="false">Contact</button>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">...</div>
<div class="tab-pane fade" id="profile" role="tabpanel" aria-labelledby="profile-tab">...</div>
<div class="tab-pane fade" id="contact" role="tabpanel" aria-labelledby="contact-tab">...</div>
</div>
I need tabs ID once its related button is clicked.
Your script is only finding the first button[data-bs-toggle="tab"] you need to use document.querySelectorAll('button[data-bs-toggle="tab"]') then loop through the NodeList.
Edit
Selecting the actual active tab-pane element takes a little more legwork. The event.target and event.relatedTarget are the tab buttons and their data-bs-target attribute value is the selector for the associated tab-pane.
Checkout the updated snippet:
var tabEl = document.querySelectorAll('button[data-bs-toggle="tab"]')
//console.log(tabEl)
for (i = 0; i < tabEl.length; i++) {
tabEl[i].addEventListener('shown.bs.tab', function(event) {
const activated_pane = document.querySelector(event.target.getAttribute('data-bs-target'))
const deactivated_pane = document.querySelector(event.relatedTarget.getAttribute('data-bs-target'))
console.log(activated_pane.id)
// console.log(deactivated_pane.id)
// do stuff
activated_pane.append(' hello ' + activated_pane.id)
})
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.1/dist/css/bootstrap.min.css" rel="stylesheet">
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="home-tab" data-bs-toggle="tab" data-bs-target="#home" type="button" role="tab" aria-controls="home" aria-selected="true">Home</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="profile-tab" data-bs-toggle="tab" data-bs-target="#profile" type="button" role="tab" aria-controls="profile" aria-selected="false">Profile</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="contact-tab" data-bs-toggle="tab" data-bs-target="#contact" type="button" role="tab" aria-controls="contact" aria-selected="false">Contact</button>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">...</div>
<div class="tab-pane fade" id="profile" role="tabpanel" aria-labelledby="profile-tab">...</div>
<div class="tab-pane fade" id="contact" role="tabpanel" aria-labelledby="contact-tab">...</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.1/dist/js/bootstrap.bundle.min.js"></script>
Here's the fiddle.
You are using querySelector, which selects only first element. Use querySelectorAll, which selects all the tabs.
/*
// Using Vanilla JS
var tabEl = document.querySelectorAll('button[data-bs-toggle="tab"]')
tabEl.forEach(function(el){
el.addEventListener('shown.bs.tab', function (event) {
alert(event.target.id) // newly activated tab
// event.relatedTarget // previous active tab
})
})
*/
/*
// Using jQuery
*/
$('button[data-bs-toggle="tab"]').on('click', function (e) { // here is the new selected tab id
var selectedTabId = e.target.id;
console.log('tab changed', selectedTabId);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.1/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.1/dist/js/bootstrap.bundle.min.js"></script>
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="home-tab" data-bs-toggle="tab" data-bs-target="#home" type="button" role="tab" aria-controls="home" aria-selected="true">Home</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="profile-tab" data-bs-toggle="tab" data-bs-target="#profile" type="button" role="tab" aria-controls="profile" aria-selected="false">Profile</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="contact-tab" data-bs-toggle="tab" data-bs-target="#contact" type="button" role="tab" aria-controls="contact" aria-selected="false">Contact</button>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">...</div>
<div class="tab-pane fade" id="profile" role="tabpanel" aria-labelledby="profile-tab">...</div>
<div class="tab-pane fade" id="contact" role="tabpanel" aria-labelledby="contact-tab">...</div>
</div>

Moving nav tab based on condition

I need to move my nav tab to the subscribtion tab if a condition is met.I am blank without any idea. Any of your help is much appreciated.
My HTML code:
<div class="matches-tabs">
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation"><a class="nav-link active" id="all-matches-tab" data-toggle="tab" href="#all-matches" role="tab" aria-controls="all-matches" aria-selected="true">Home</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" id="upcoming-matches-tab" data-toggle="tab" href="#upcoming-matches" role="tab" aria-controls="upcoming-matches" aria-selected="false">Upcoming Matches</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" id="Subscription-tab" data-toggle="tab" href="#Subscription" role="tab" aria-controls="Subscription" aria-selected="false">Subscription</a></li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade show active" id="all-matches" role="tabpanel" >
Tab 1
</div>
<div class="tab-pane fade" id="upcoming-matches" role="tabpanel">
Tab 2
</div>
<div class="tab-pane fade" id="Subscription" role="tabpanel">
Tab 3
</div>
</div>
</div>
If the condition
if ($scope.balance >= matchfee){
//change the tab to subscription tab
}
is met change my tab to subscription.
As far as I can understand from your html code. You need to bind your html data from angularJS controller. EG. https://material.angularjs.org/latest/demo/tabs 'Dynamic Tabs'. For now you can only make it with CSS selectors only
But if you do not want to dynamically manage your tabs you can use ng-class like
<li class="nav-item" role="presentation"><a class="nav-link active" id="all-matches-tab" data-toggle="tab" href="#all-matches" role="tab" aria-controls="all-matches" aria-selected="true">Home</a></li>
To => ng-class="isActiveTab ? 'active' : '' "

Bootstrap: how to add a link to nav-tabs

I have the following html code:
<ul class="nav nav-pills mb-3" id="pills-tab" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="pills-home-tab" data-toggle="pill" href="#pills-home" role="tab" aria-controls="pills-home" aria-selected="true">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" id="pills-profile-tab" data-toggle="pill" href="#pills-profile" role="tab" aria-controls="pills-profile" aria-selected="false">Profile</a>
</li>
<li class="nav-item">
<a class="nav-link" id="pills-contact-tab" data-toggle="pill" href="#pills-contact" role="tab" aria-controls="pills-contact" aria-selected="false">Contact</a>
</li>
</ul>
<div class="tab-content" id="pills-tabContent">
<div class="tab-pane fade show active" id="pills-home" role="tabpanel" aria-labelledby="pills-home-tab">...</div>
<div class="tab-pane fade" id="pills-profile" role="tabpanel" aria-labelledby="pills-profile-tab">...</div>
<div class="tab-pane fade" id="pills-contact" role="tabpanel" aria-labelledby="pills-contact-tab">...</div>
</div>
I want that when I click on the second tab "Profile" it redirects to a new link (ad example "myapp/test").
How could I do it?
Correct me if I am wrong: If the user clicks on the Profile tab, this should navigate to another site instead of opening the Profile tab.
Remove the data-toggle from the <a> element and put your link inside the href attribute. The data-toggle attribute tells Bootstrap what to do if the user clicks in that element. Bootstrap uses the 'href` attribute to find the corresponding element.
<ul class="nav nav-pills mb-3" id="pills-tab" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="pills-home-tab" data-toggle="pill" href="#pills-home" role="tab" aria-controls="pills-home" aria-selected="true">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" id="pills-profile-tab" href="#pills-profile" role="tab" aria-controls="pills-profile" aria-selected="false">Profile</a>
</li>
<li class="nav-item">
<a class="nav-link" id="pills-contact-tab" data-toggle="pill" href="myapp/test" role="tab" aria-controls="pills-contact" aria-selected="false">Contact</a>
</li>
</ul>
<div class="tab-content" id="pills-tabContent">
<div class="tab-pane fade show active" id="pills-home" role="tabpanel" aria-labelledby="pills-home-tab">...</div>
<div class="tab-pane fade" id="pills-profile" role="tabpanel" aria-labelledby="pills-profile-tab">...</div>
<div class="tab-pane fade" id="pills-contact" role="tabpanel" aria-labelledby="pills-contact-tab">...</div>
</div>

nav-pills url is lost at page refresh

I encounter following problems when using bs4 toggled nav-pills wrapped inside a nav tabs submenu:
next url doesn't load pill with id option2: http://localhost/test#option2 although if I click on it it switches to that pill.
When I am on pill with id option2 and I do page refresh it gets back to first pill - the one with id option1
I need to have a functional link for each pill which should open that specific pill and should be persistent at page refresh - I think it is called deep linking but examples I found are either different or old.
<nav>
<div class="nav nav-tabs" id="nav-tab" >
<a class="nav-item nav-link disabled" id="nav-menu1-tab" href="#">menu1</a>
<a class="nav-item nav-link active" id="nav-menu2-tab" href="#nav-menu2">active-tab</a>
<a class="nav-item nav-link disabled" id="nav-menu3-tab" href="#">menu3</a>
</div>
</nav>
<div class="tab-content" id="nav-tabContent">
<div class="tab-pane fade show active" id="nav-menu2"></div>
<ul class="nav nav-pills mb-3" id="pills-tab" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="pills-option1-tab" data-toggle="pill" href="#option1" role="tab" aria-controls="pills-option1" aria-selected="true">option1</a>
</li>
<li class="nav-item">
<a class="nav-link" id="pills-option2-tab" data-toggle="pill" href="#option2" role="tab" aria-controls="pills-option2" aria-selected="false">option2</a>
</li>
</ul>
<div class="tab-content" id="pills-tabContent">
<div class="tab-pane fade show active" id="option1" role="tabpanel" aria-labelledby="pills-option1-tab">option1...</div>
<div class="tab-pane fade" id="option2" role="tabpanel" aria-labelledby="pills-option2-tab">option2...</div>
</div>
</div>

Categories

Resources