assaqqaf
assaqqaf

Reputation: 1585

How to use AJAX loading with Bootstrap tabs?

I used bootstrap-tabs.js and it has worked perfectly.

But I didn't find information about how to load content through AJAX request.

So, how to use AJAX loading with bootstrap-tabs.js?

Upvotes: 44

Views: 98898

Answers (10)

user1177811
user1177811

Reputation: 643

I wanted to load fully dynamic php pages into the tabs through Ajax. For example, I wanted to have $_GET values in the links, based on which tab it was - this is useful if your tabs are dynamic, based on database data for example. Couldn't find anything that worked with it but I did manage to write some jQuery that actually works and does what I'm looking for. I'm a complete jQuery noob but here's how I did it.

  1. I created a new 'data-toggle' option called tabajax (instead of just tab), this allows me to seperate what's ajax and what's static content.
  2. I created a jQuery snippet that runs based on that data-toggle, it doesn't mess with the original code.

I can now load say url.php?value=x into my Bootstrap Tabs.

Feel free to use it if you want to, code is below

jQuery code:

$('[data-toggle="tabajax"]').click(function(e) {
    e.preventDefault()
    var loadurl = $(this).attr('href')
    var targ = $(this).attr('data-target')
    $.get(loadurl, function(data) {
        $(targ).html(data)

    });
    $(this).tab('show')
});

HTML:

<li><a href="tabs/loadme.php?value=1" data-target='#val1' data-toggle="tabajax">Val 1</a></li>

So here you can see that I've changed the way bootstrap loads thing, I use the href for the dynamic ajaxlink and then add a 'data-target' value to the link instead, that should be your target div (tab-content).

So in your tab content section, you should then create an empty div called val1 for this example.

Empty Div (target):

<div class='tab-pane' id='val1'><!-- Ajax content will be loaded here--></div>

Hope this is useful to someone :)

Upvotes: 25

Owen
Owen

Reputation: 593

In Bootstrap 2.0 and up you have to bind to the 'show' event instead.

Here's an example HTML and JavaScript:

<div class="tabbable">
    <ul class="nav nav-tabs" id="myTabs">    
        <li><a href="#home"  class="active" data-toggle="tab">Home</a></li>
        <li><a href="#foo" data-toggle="tab">Foo</a></li>
        <li><a href="#bar" data-toggle="tab">Bar</li>
    </ul>
    <div>
        <div class="tab-pane active" id="home"></div>
        <div class="tab-pane" id="foo"></div>
        <div class="tab-pane" id="bar"></div>
    </div>
</div>

JavaScript:

$(function() {
    var baseURL = 'http://yourdomain.com/ajax/';
    //load content for first tab and initialize
    $('#home').load(baseURL+'home', function() {
        $('#myTab').tab(); //initialize tabs
    });    
    $('#myTab').bind('show', function(e) {    
       var pattern=/#.+/gi //use regex to get anchor(==selector)
       var contentID = e.target.toString().match(pattern)[0]; //get anchor         
       //load content for selected tab
       $(contentID).load(baseURL+contentID.replace('#',''), function(){
            $('#myTab').tab(); //reinitialize tabs
       });
    });
});

I wrote a post about it here: http://www.mightywebdeveloper.com/coding/bootstrap-2-tabs-jquery-ajax-load-content/

Upvotes: 39

Marcelo Agim&#243;vel
Marcelo Agim&#243;vel

Reputation: 1719

I use this function and it's really nice because she prevent's you from load ajax again when going back to that tab.

Tip: on tab href, just put the destination. Add this to footer:

$("#templates_tabs").tabs({
    beforeLoad: function( event, ui ) {
      if (ui.tab.data("loaded")) {
          event.preventDefault();

          return;
      }


      ui.ajaxSettings.cache = false,
      ui.jqXHR.success(function() {

          ui.tab.data( "loaded", true );
      }),
      ui.jqXHR.error(function () {


          ui.panel.html(
          "Not possible to load. Are you connected?");
      });
    }
  });

Upvotes: 1

Nikunj K.
Nikunj K.

Reputation: 9199

Here is the Bootstrap tab Ajax example, you can use it...

<ul class="nav nav-tabs tabs-up" id="friends">
      <li><a href="/gh/gist/response.html/3843293/" data-target="#contacts" class="media_node active span" id="contacts_tab" data-toggle="tabajax" rel="tooltip"> Contacts </a></li>
      <li><a href="/gh/gist/response.html/3843301/" data-target="#friends_list" class="media_node span" id="friends_list_tab" data-toggle="tabajax" rel="tooltip"> Friends list</a></li>
      <li><a href="/gh/gist/response.html/3843306/" data-target="#awaiting_request" class="media_node span" id="awaiting_request_tab" data-toggle="tabajax" rel="tooltip">Awaiting request</a></li>
</ul>

<div class="tab-content">
<div class="tab-pane active" id="contacts">
</div>
      <div class="tab-pane" id="friends_list">

      </div>
      <div class="tab-pane  urlbox span8" id="awaiting_request">

      </div>
    </div>

and here is the AJAX call

$('[data-toggle="tabajax"]').click(function(e) {
    var $this = $(this),
        loadurl = $this.attr('href'),
        targ = $this.attr('data-target');

    $.get(loadurl, function(data) {
        $(targ).html(data);
    });

    $this.tab('show');
    return false;
});

Upvotes: 1

ukessi
ukessi

Reputation: 1391

You can listen the change event and ajax load content in the event handler

$('.tabs').bind('change', function (e) {
    var now_tab = e.target // activated tab

    // get the div's id
    var divid = $(now_tab).attr('href').substr(1);

    $.getJSON('xxx.php').success(function(data){
        $("#"+divid).text(data.msg);
    });
})

Upvotes: 38

m00seDrip
m00seDrip

Reputation: 4021

This is an MVC example using Razor. It will interact with two partial views named: _SearchTab.cshtml and _SubmissionTab.cshtml

Notice that I am naming the id of the tabs the same as the partials.

Markup:

<!-- Nav tabs -->
<ul id="tabstrip" class="nav nav-tabs" role="tablist">
    <li class="active"><a href="#_SubmissionTab" role="tab" data-toggle="tab">Submission</a></li>
    <li><a href="#_SearchTab" role="tab" data-toggle="tab">Search</a></li>
</ul>

<!-- Tab panes -->
<div class="tab-content">
    <div class="tab-pane fade in active" id="_SubmissionTab">@Html.Partial("_SubmissionTab")</div>
    <div class="tab-pane fade" id="_SearchTab"></div>
</div>

The @Html.Partial will request the page on the active tab on page load

Script:

<script>
    $('#tabstrip a').click(function (e) {
        e.preventDefault()
        var tabID = $(this).attr("href").substr(1);
        $("#" + tabID).load("/@ViewContext.RouteData.Values["controller"]/" + tabID)
        $(this).tab('show')
    })
</script>

The load function will perform an ajax request as each tab is clicked. As for what path is requested you will notice a @ViewContext.RouteData.Values["controller"] call. It simply gets the controller of the current view assuming the partial views are located there.

Controller:

    public ActionResult _SubmissionTab()
    {
        return PartialView();
    }

    public ActionResult _SearchTab()
    {
        return PartialView();
    }

The controller is needed to relay the load request to the proper partial view.

Upvotes: 1

Pierre de LESPINAY
Pierre de LESPINAY

Reputation: 46178

I suggest to put the uri into the tab-pane elements, it allows to take advantage of web frameworks reverse url fonctionnalities. It also allows to depend exclusively on the markup

<ul class="nav nav-tabs" id="ajax_tabs">
  <li class="active"><a data-toggle="tab" href="#ajax_login">Login</a></li>
  <li><a data-toggle="tab" href="#ajax_registration">Registration</a></li>
</ul>
<div class="tab-content">
  <div class="tab-pane active" id="ajax_login"
    data-target="{% url common.views.ajax_login %}"></div>
  <div class="tab-pane" id="ajax_registration"
    data-target="{% url common.views.ajax_registration %}"></div>
</div>

And here is the javascript

function show_tab(tab) {
    if (!tab.html()) {
        tab.load(tab.attr('data-target'));
    }
}

function init_tabs() {
    show_tab($('.tab-pane.active'));
    $('a[data-toggle="tab"]').on('show', function(e) {
        tab = $('#' + $(e.target).attr('href').substr(1));
        show_tab(tab);
    });
}

$(function () {
    init_tabs();
});

I loads the active tab, and loads a tab only if it is not already loaded

Upvotes: 9

howler
howler

Reputation: 13

Here is a solution I have found - and modified to suit my needs:

$("#tabletabs").tab(); // initialize tabs
$("#tabletabs").bind("show", function(e) { 
var contentID = $(e.target).attr("data-target");
var contentURL = $(e.target).attr("href");
if (typeof(contentURL) != 'undefined') { // Check if URL exists
$(contentID).load(contentURL, function(){
$("#tabletabs").tab(); // reinitialize tabs
});
} else {
$(contentID).tab('show');
}
});
$('#tabletabs a:first').tab("show"); // Load and display content for first tab
});

Upvotes: 1

Matt R.
Matt R.

Reputation: 2279

Here is how I do it. I utilize an attribute data-href which holds the url I want to load on show. This will not reload data that is already loaded unless you set $('#tab').data('loaded'); to 0 or remove it. It also handles relative vs. absolute urls by detecting the location of the first slash. I am not sure of the compatibility with all browsers but it works in our situation and allows for the functionality we are looking for.

Javascript:

//Ajax tabs
$('.nav-tabs a[data-href][data-toggle="tab"]').on('show', function(e) {
  var $this = $(this);
  if ($this.data('loaded') != 1)
  {
    var firstSlash = $this.attr('data-href').indexOf('/');
    var url = '';
    if (firstSlash !== 0)
      url = window.location.href + '/' + $this.attr('data-href');
    else
      url = $this.attr('data-href');
    //Load the page

    $($this.attr('href')).load(url, function(data) {
      $this.data('loaded', 1);
    });
  }
});

HTML:

<div class="tabbable">
  <ul class="nav nav-tabs">
    <li class="active">
      <a href="#js-tab1" data-href="tab1.php" data-toggle="tab">Tab 1</a>
    </li>
  </ul>
  <div class="tab-content">
    <div class="tab-pane active" id="js-tab1">
      <p>
        This content isn't used, but instead replaced with contents of tab1.php.
      </p>
      <p>
        You can put a loader image in here if you want
      </p>
    </div>
  </div>
</div>

Upvotes: 2

jmartsch
jmartsch

Reputation: 352

There is an error in your code user1177811.

It has to be $('[data-toggle="tabajax"]').

Also there is room for improvement. The .load() method, unlike $.get(), allows us to specify a portion of the remote document to be inserted. So i added #content to load the content div of the remote page.

$this.tab('show'); is now only called, when response was a success.

Here is the code

 $('[data-toggle="tabajax"]').click(function(e) {
        e.preventDefault();
        $this = $(this);
        var loadurl = $(this).attr('href');
        var targ = $(this).attr('data-target');
        $(targ).load(loadurl+'?ajax=true #content', function(){
            $this.tab('show');
        });
    });

Upvotes: 2

Related Questions