Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Capturing 'shown' event from bootstrap tab

I have some 'static' HTML on my page:

<div id="DIVISIONS">     <ul class="nav nav-tabs" id="DIVISIONTABS">         @* <li> nodes will be injected here by javascript *@     </ul>     <div class="tab-content" id="DIVISIONTABPANES">         @* <div class="tab-pane"> nodes will be injected here by javascript *@     </div> </div> 

On page load, I create a tab 'framework', i.e. create the bootstrap tabs and tab content containers.

I trigger the process with:

$(window).bind("load", prepareDivisionTabs); 

And "prepareDivisionTabs" does this:

function prepareDivisionTabs() {     // Retrieve basic data for creating tabs     $.ajax({         url: "@Url.Action("GetDivisionDataJson", "League")",         cache: false     }).done(function (data) {         var $tabs = $('#DIVISIONTABS').empty();         var $panes = $('#DIVISIONTABPANES').empty();         for (var i = 0; i < data.length; i++) {             var d = data[i];             $tabs.append("<li><a href=\"#TABPANE" + d.DivisionId + "\" data-toggle=\"tab\">" + NMWhtmlEncode(d.Name) + "</a></li>");             $panes.append("<div id=\"TABPANE" + d.DivisionId + "\" class=\"tab-pane\"></div>")         }         renderDivisionTabPaneContents(data);     }).fail(function (err) {         alert("AJAX error in request: " + JSON.stringify(err, null, 2));     }); } 

For info, the "renderDivisionTabPaneContents" in the above does this:

function renderDivisionTabPaneContents(data) {     for (var i = 0; i < data.length; i++) {         var d = data[i];         renderDivisionTabPaneContent(d.DivisionId);     } }  function renderDivisionTabPaneContent(id) {     var $tabPane = $('#TABPANE' + id);     $tabPane.addClass("loader")     $.ajax({         url: "/League/GetDivisionPartialView?divisionId=" + id,         cache: false     }).done(function (html) {         $tabPane.html(html);     }).fail(function (err) {         alert("AJAX error in request: " + JSON.stringify(err, null, 2));     }).always(function () {         $tabPane.removeClass("loader")     }); } 

All good so far. My page loads, my tab contents are rendered, and when I click the different tabs, the relevant content is shown.

Now, rather than loading all content at the start, I want to load tab content just-in-time by using the 'shown' event of the tabs. To test this, I've wanted to just make sure I could get a javascript alert when the tab was shown. So, I create the following to trigger the attachment of tab shown events:

$(function () {     attachTabShownEvents(); }) 

which calls:

function attachTabShownEvents() {     $(document).on('shown', 'a[data-toggle="tab"]', function (e) {         alert('TAB CHANGED');     }) } 

I'd therefore expect so see the "TAB CHANGED" alert after the change of tab. But ... I see no alerts.

Could anybody help me out here?

like image 291
Neil W Avatar asked Nov 02 '13 12:11

Neil W


1 Answers

The correct event binding for tab change is shown.bs.tab.

$(document).on('shown.bs.tab', 'a[data-toggle="tab"]', function (e) {     alert('TAB CHANGED'); }) 

Update 11-01-2020 --- Bootstrap 4.5

This is still the correct answer however, this is a bit of additional helpful information found all the way at the bottom of the official bootstrap docs page at: https://getbootstrap.com/docs/4.5/components/navs/#tabs

$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {   e.target // newly activated tab   e.relatedTarget // previous active tab }) 

You can determine which tab has been selected each time the code fires with e.target.

If you have unique IDs on your elements then you could do something like the following so code only runs when the appropriate tab is clicked.

$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {   switch (e.target.id){       case "mainTab":{            doMainTabStuff();            break;       }       case "configTab":{            doConfigTabStuff();            break;       }   } }) 
like image 104
azz Avatar answered Sep 20 '22 14:09

azz