How to use AJAX loading with Bootstrap tabs? - ajax

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?

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>Home</li>
<li>Foo</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/

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);
});
})

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.
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.
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>Val 1</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 :)

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

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');
});
});

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">
Tab 1
</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>

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
});

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">Submission</li>
<li>Search</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.

Here is the Bootstrap tab Ajax example, you can use it...
<ul class="nav nav-tabs tabs-up" id="friends">
<li> Contacts </li>
<li> Friends list</li>
<li>Awaiting request</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;
});

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?");
});
}
});

Related

On button click reload content (ajax) in tab

I'm using jquery ui tabs. Every tab get content via ajax load. How can I reload content in active tab when I click the button or when the form in content is submitted.
So far I've got this.. (that works).
HTML
<div id="tabs">
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
</div>
Refresh
JS
<script>
$( function() {
$( "#tabs" ).tabs({
beforeLoad: function( event, ui ) {
ui.jqXHR.fail(function() {
ui.panel.html(
"Vsebine ni mogoče prikazati. Poskusite kasneje." );
});
}
});
} );
</script>
The widget provides the load method ( https://api.jqueryui.com/tabs/#method-load ) specifically for this purpose:
$("#btn-osvezi2").click(function() {
var index = $("#tabs").tabs("option", "active");
$("#tabs").tabs("load", index);
});

bootstrap tab('show') not work on dynimcally loaded 'tab-content'

I am using ASP.NET MVC and boostrap 3
I am using bootstrap tabs,
my main view like this
<div class="row">
<div class="tabs-container">
<ul class="nav nav-tabs" id="test">
<li class="active"><a data-toggle="tab" href="#tab-operations">Operations</a></li>
<li class=""><a data-toggle="tab" href="#tab-categories">Categories</a></li>
</ul>
#Html.Partial("_Ordering", Model)
</div>
</div>
the partial view _Ordering like this
<div class="tab-content" id="ordDiv">
<div id="tab-operations" class="tab-pane active">
// some content not important
</div>
<div id="tab-categories" class="tab-pane">
// some content not important
</div>
</div>
and I am using unobtrusive-ajax to update the partial view
#Ajax.ActionLink("cancel", "PartialOrdering", null,
new AjaxOptions { HttpMethod = "GET", Url = Url.Action("PartialOrdering"), UpdateTargetId = "ordDiv", InsertionMode = InsertionMode.Replace }, null)
the content of the tab updating correctly wihout any problem.
the problem is i want to show the tab which already was exists before the ajax request refreshed the content.
I used js code for this like this
var a = $('#test li.active').find('a');
a.click(); // not showing the content of the tab
a.tab('show'); // also this not showing the content of the tab
the previous code does not make any error in the console, but the desired tab is not shown
If you want to show a specific tab here you will need to pass the id of specific anchor tag and based on that anchor you can call the tab() function.
$(document).ready(function(){
activeaTab('tab-categories');
});
function activeaTab(tab){
$('.nav-tabs a[href="#' + tab + '"]').tab('show');
};
https://jsfiddle.net/ewaeLkvv/

angular: Why won't ng-repeat update with data from ajax call?

From a controller a do a ajax call. The call can be triggered from two different links, both in the same html template. When using the above link that switches to the tab the data returned by the ajax call is displayed correctly. When using the refresh link the element in the ng-repeat won't be updated. Anyone knows why this is?
angularjs:
app.controller("ActiveSimulations",
["$scope", "$http", "socket",
function($scope, $http, socket){
$scope.active_simulations_dict = {};
$scope.get_active_simulations = function() {
var responsePromise = $http.get("/active_simulations");
responsePromise.success(function (data, status, headers, config) {
$scope.active_simulations_dict = data;
console.log($scope.active_simulations_dict)
});
responsePromise.error(function (data, status, headers, config) {
console.log('Warning - "AJAX failed!"')
alert("AJAX failed!");
});
};
}]);
HTML
<div id="followSim" class="tab-pane fade">
<h3>Follow running simulations</h3>
<div class="inline-containers">
<div id="simulation-list-wrapper">
<ul class="list-unstyled">
<li ng-repeat="(key, value) in active_simulations_dict">
<a ng-show="value[0] && value[2]" ng-click="followActiveSimulation(key)">
{[{ value[0] }]} ( {[{ value[2] }]} is director)
</a>
</li>
</ul>
</div> <!--end simulation list wrapper-->
<div id="refresh-simulation-list" ng-controller="ActiveSimulations">
<a id="refresh-link"
class="right-side"
ng-click="get_active_simulations()">
<i class="icon-refresh right-side"></i>
refresh list
</a>
</div>
As #kasoban pointed out you might have an issue with multiple instances. Best practice is to create a service which handles your requests. You can inject it and call the request function from any controller then e.g.:
$scope.active_simulations_dict = RequestService.get_active_simulations();

Returning data from dynamic (AJAX) loaded Bootstrap Modal

I am using Bootstrap modal's in a Codeigniter application as a popup WYSIWYG text-editor. Everything in regards to loading content, and the modal, works fine. I can even save the content when the modal is open via AJAX.
But what I am trying to accomplish is when I hit the "Save" button in my modal... I want to return the value — $('#wysiwyg').val() — to the page that opened the modal.
Link triggering the modal
Write Text
JavaScript loading modal - Modified source from https://gist.github.com/drewjoh/1688900
$('.ajax-modal').click(function(e) {
e.preventDefault();
var modal = $('#ajax-modal');
var url = $(this).attr('href');
if(url.indexOf('#') == 0) {
$(url).modal('open');
} else {
$.get(url, function(data) {
modal.html(data);
modal.modal();
}).success(function() {
/* boom. loaded. */
});
}
});
HTML modal wrapper
<div id="ajax-modal" class="modal hide fade" data-backdrop="static" data-keyboard="false" tabindex="-1"></div>
HTML modal body/contents
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3>Text Editor</h3>
</div>
<div class="modal-body">
<textarea class="input-block-level" id="wysiwyg" rows="9">Write something...</textarea>
</div>
<div class="modal-footer">
<button class="btn btn-link" data-dismiss="modal" aria-hidden="true">Cancel</button>
<button id="submit-modal" class="btn btn-success">Save</button>
</div>
Thanks in advance.
You could try something like this:
var modal = $('#ajax-modal');
// Filter clicks within the modal to those on the save button (#submit-modal)
modal.on('click', '#submit-modal', function(e) {
// Find the wysiwyg within the modal
var wysiwyg = $('#wysiwyg', modal);
// Now do what you want with wysiwyg.val();
if (wysiwyg.length) $('#my_info_div').html(wysiwyg.val());
});
I think I get what you are asking for...There are a few ways you can do this. If you want to create a more separated approach you could use a pub/sub framework like Amplify. The simplest approach would be to create a reference to the element you want to populate prior to creating the click event. Like so:
var controlToPopulate = $("#controlToPopulateId");
$('.ajax-modal').click(function(e) {
e.preventDefault();
var modal = $('#ajax-modal');
var url = $(this).attr('href');
if(url.indexOf('#') == 0) {
$(url).modal('open');
} else {
$.get(url, function(data) {
modal.html(data);
modal.modal();
}).success(function() {
/* boom. loaded. */
modal.find('#submit-modal').click(function() {
controlToPopulate.val(modal.find('#wysiwyg').val());
});
});
}
});
When you wrote if(url.indexOf('#') == 0), did you mean if(url.indexOf('#') == -1)? indexOf('#') returns -1 if # does not appear in the string.

Twitter-Bootstrap tabs load container content via AJAX

I'm trying to implement this example for Twitter-Bootstrap tabs http://www.dba-resources.com/scripting-programming/ajax-tabs-in-bootstrap-2-1/ loading content via AJAX, but I need to load the content from a div container within the same document, rather than loading multiple documents. The code I'm using is as follows:
jQuery
$(function() {
$("#MainTabs").tab();
$("#MainTabs").bind("show", function(e) {
var contentID = $(e.target).attr("data-target");
var contentURL = $(e.target).attr("href");
if (typeof(contentURL) != 'undefined')
$(contentID).load(contentURL, function(){ $("#MainTabs").tab(); });
else
$(contentID).tab('show');
});
$('#MainTabs div[data-target="#tabone"]').tab("show");
});
HTML
<ul id="MainTabs" class="nav nav-tabs">
<li><div data-target="#tabone" data-toggle="tab">tab One</div></li>
<li><div data-target="#tabtwo" data-toggle="tab" href="/test.html">Tab Two</div></li>
<li><div data-target="#tabthree" data-toggle="tab" href="/test2.html">Tab Three</div></li>
</ul>
<div class="tab-content">
<div class="tab-pane" id="tabone">Content Tab One</div>
<div class="tab-pane" id="tabtwo">Loading...</div>
<div class="tab-pane" id="tabthree">Loading...</div>
</div>
Thank you in advance for any help.
That should be the default behavior if you just pass in the id of the container to the href.
<li><div data-target="#tabone" data-toggle="tab" href="#loadedcontent">tab One</div></li>
....
<div id="loadedcontent">My content</div>
Since you have a special case where you want to load a specific container of the page through an AJAX call. You can do something like this.
HTML
<li><div id="specialTab" data-target="#tabone" data-toggle="tab" href="/ajax.html">tab one</div></li>
JS
$('#specialTab').click(function(e) {
e.preventDefault();
var containerId = '#content'; /** Specify which element container */
var self = $(this);
var url = self.attr('href');
$(self.data('target'))
.load(url +' '+ containerId, function(){
self.tab('show');
});
});

Resources