Issue with jQuery UI Tabs (loaded via ajax) and form data - ajax

I am attempting to set up an interface that has a form containing filters about some jQuery UI Tabs. The tabs are loaded via ajax.
When I click on one of the tabs, I want the data from the form to be submitted to that tab.
I set up the ajaxOptions to grab the data from my form, serialize it, and POST it to the url. I have caching turned OFF, and I have caching for the ajaxOptions turned OFF.
This is the code I am using to set up the tabs.
$("#schedule-tabs").tabs({
ajaxOptions: {
type: 'POST',
data: $('#filters').serialize(),
cache: false,
error: function(xhr, status, index, anchor) {
$(anchor.hash).html("<p>An error has been encountered while attempting to load this tab.</p>");
}
},
cache: false
});
When the tabs load, the data that is passed along is the data that was in the form when the page was first loaded even though I have changed the filters in the form.
I have added the following to the above tab setup to verify the form data along the way:
select: function(event, ui) {
alert($('#filters').serialize());
},
load: function(event, ui){
alert($('#filters').serialize());
},
show: function(event, ui){
alert($('#filters').serialize());
}
In all 3 instances, the updated form data is alerted. However, when the data reaches my page, it is the original data not the new data.
It appears that something is being cached somewhere, but I have no clue where.
Shouldn't the data be grabbed fresh from the form for each ajax page load? Why is it being cached? Is there some other way that I can override the data that is being posted when the tab content loads?
This is a huge blocker in my current project. If I can't resolve it soon, I will have to find some other solution other than the jQuery UI Tabs. I want to use them, but if this issue can't be resolved ...
Can anyone help???

I believe I have figured out the answer to my own question. I wanted to share in case others have run into this same situation.
Basically, I added an option that when a tab is selected, it gets the current form data and resets the ajaxOptions.
The code I am now using is:
// set up the jQuery UI Tabs
var $tabs = $("#schedule-tabs").tabs({
ajaxOptions: {
type: 'POST',
data: $('#filters').serialize(),
cache: false,
error: function(xhr, status, index, anchor) {
$(anchor.hash).html("<p>An error has been encountered while attempting to load this tab.</p>");
}
},
cache: false,
select: function(event, ui) {
// get the current form data
var filter_options = $('#filters').serialize();
// update the data for the ajax options
$(this).tabs('option', 'ajaxOptions', { type: 'POST', 'data': filter_options });
return true;
}
});
I hope this helps someone else out.

Related

Selectors not working on ajax response

I'm using ajax to submit pages and return content blocks based on user action for an onboarding sequence.
If have a page which loads and get 1 content element, the user then clicks Yes or No, which loads the next content element into the same space (via ajax).
For some reason my selectors don't seem to be working on that ajax loaded html.
Here is my ajax function which gets the form:
$.ajax({
beforeSend: function() {
$("#loader").toggleClass('progress');
},
type: 'POST',
dataType: 'json',
data: data,
url: baseUrl+'welcome/user_confirmation_form',
complete: function( response ) {
$("#loader").toggleClass('progress');
},
success: function( response ) {
console.log(response);
$("div.welcome-page > .col").html(response.response);
},
error: function( response ) {
$("#next-steps").html(response.response);
}
});
I'm then trying to access the submit button (have tried doing it as a ahref and button type=submit but nothing seems to be selecting the event.
$('div.welcome-page').on('submit', "user_complete", function(e) {
e.preventDefault();
console.log('FOund form');
var user = $(this).serializeArray();
console.log(user);
});
If I view source, the ajax returned HTML is not even in the dom, but it is when viewing the UI normally.
I'm guessing this has something to do with it?
How can I select all the form data?
Any time I click on the button or ahref it just fires the same page again.
If user_complete is a class you are assigning on your submit button in your loaded html, then you are missing a .
$('div.welcome-page').on('submit', ".user_complete", function(e) {
But this will only work if you're using a submit action as this is listening for a submit event. Maybe you want to listen for a click event?
You need to bind the events to your handlers for your newly added HTML elements. Your original call to
$('div.welcome-page').on('submit' ...
Only bound the event handler for the elements that were on the page at that point in time.
You can put your handler into a function ...
var myHandler = function(e) {
e.preventDefault();
var user = $(this).serializeArray();
}
And then after you load the new HTML you need to bind the handler to the event. So, on success with the AJAX you would ...
success: function( response ) {
$("div.welcome-page > .col").html(response.response);
$('div.welcome-page').on('submit', "user_complete", myHandler);
},

Not able to post JSON Data to MVC Action Method using $.AJAX but I get a Post 200 OK Response

I am trying to post some stringified data to an action method in my MVC controller. Below is the piece of JS Code
function SaveStateForGrid(pGridId, pIsAysnc) {
var grid = $('#' + pGridId).data("kendoGrid");
var tGridState = kendo.stringify(grid.getOptions());
$.ajax({
url: '/Home/SaveGridState',
type: 'POST',
dataType: 'json',
async: pIsAysnc,
data: { pGridState: tGridState, pGridName: pGridId },
success: function (data) {
console.log("Data Saved Successfully");
},
error: function (jqXHR, textStatus) {
console.log("Error while saving grid data " + pGridId);
}
});
}
I am trying to save gridstate info into the db and each grid in my app has different grid state info.
This works sometimes - as in, the post hits the controller method "SaveGridState" if I keep a breakpoint there and so on. On other occasions the breakpoint is not hit and the data is not saved in DB but the code does flow to "success" AJAX callback - no errors and I get a 200POST OK response in the network tab of chrome debugger.
I looked up the data being sent and figured out that on the occasions it fails, there is something about the data being posted which is causing it. Specifically the first param - "tGridState" - a stringified KendoGrid config data. If I replace this data from other successful calls, there is no issue. I have compared the data on different viewing tools and am not able to understand what in the data is breaking this.
Attaching a link to the zip file which contains both "Valid" and "Invalid" data. Any help pls ?
https://www.dropbox.com/s/whfglyk607bnd04/Downloads.zip?dl=0
Few months on from posting this - the module in question was on freeze.
I discovered that the stringified gridstate information (grid config data) included JS functions for grid related events which was causing issues in the stringified data. In fact stringification strips such functions from an object.
Somehow this was preventing me from hitting the breakpoint on the server side even if the data was posted "apparently".
So I wrote a JS function to strip all unnecessary data from my gridstate config data before stringification - and then the post works perfectly.
Voila !

Odd bug in my jQuery seems to prevent an event from firing

I have an ajax request as follows:
jQuery.ajax({
type: 'GET',
url: '/logical_interface/delete',
context: this, // had to add this to get the line in the success function to work, never used it before nor do I understand why it works
data: 'id=' + id,
beforeSend: function() {
// jQuery(this).parent().html('processing...');
// if this line is uncommented then the DOM will be updated correctly
// but the snippet in the success function won't fire but the delete
// is still executed on the server side
// the page is then stuck with the 'processing' text
},
success: function(data) {
jQuery(this).closest('tr').stop().animate({ backgroundColor: '#ffc6be' }, 'fast').hide('slow');
}
});
Update
Server side code is simply the following Rails method:
def delete
#logical_interface = LogicalInterface.find(params[:id])
#logical_interface.destroy
render :text => '1' // which is what I get in console.log
end
As mentioned in comments, the reason your success may not work is because you deleted the $(this) node.
What you are doing in your beforeSend function is going up one level and replacing ALL HTML with "processing...". This in turn deleted your reference point jQuery(this) from the DOM before the success case is reached. if jQuery(this) is removed then nothing happens (obvious).
Instead of overwriting the entire html with Processing, may i suggest you have a single element hidden until you trigger the ajax and show it beforeSend and hide it with the complete function.

Load Ajax Content to Hidden Tab - Instead of Current Tab

I have a dashboard UI that utilizes a jQuery tabs script. Each tab loads its content via separate Ajax requests.
Here's the issue I'm having:
A user will open multiple tabs, one right after the other
Each tab is created and an Ajax request is made for each
The last tab to be created is currently open and each tab's content is displayed on this tab once the requests are complete
Once a user clicks on any tab, the content is set as it should be.
Basically, if the user opens a new tab ahead of a recent tab's Ajax request completing, both Ajax requested contents display on the current open tab until the user clicks on any tab and then everything is displayed as it should be.
I've tried setting the Ajax calls to async: false which solves the issue as it forces the ajax requests to complete and load on the current tab before allowing the user to open another tab, however the user feedback has been negative in that users think that the dashboard froze (which it has).
I've also set a timeout function to load the tab with a loading .gif and then make the async: false Ajax request. The user feedback as been the same, even with the timeout function as the loading gif stops it's animation once the Ajax request is made.
The Ajax requests looks like this:
$.ajax ({
url: report,
cache: false,
success: function(html) {
$("#loading").hide();
$("#tabcontent").append('<div id="c'+count+'" class="tabContentContainer">'+html+'</div>');
},
error: function(x, status, error) {
$.ajax ({
url: 'admin/error_notification.php',
type: "POST",
data:{
error: error
}
});
},
async:true
});
Keep track of the last request in some way and abort it when creating another request:
var jqxhr = {abort: function () {}};
/* various other code */
function loadTabOrWhatever() {
jqxhr.abort();
jqxhr = $.ajax({
/* ajax call in your question */
I would suggest having a separate tabcontent div that is paired with each tab (not just one #tabcontent div), and show/hide those when switching tabs. Then if a previous ajax call comes back later, and populates a tabcontent div that is now hidden, there's no harm done.
function loadTab(tabName) {
// Hide all tab content panes, then just show the one we want
$(".tab-pane").hide();
$("#tab-" + tabName).show();
$.ajax ({
...
success: function(html) {
$("#loading").hide();
$("#tab-" + tabName).append('<div id="c'+count+'" class="tabContentContainer">'+html+'</div>');
<snip>
Create your content panes like:
<div class="tab-pane" id="tab-firsttab"></div>
And trigger links would be something along the lines of:
First Tab
I believe it would make it harmless then for users to quickly click on multiple tabs, firing off multiple ajax calls, since each ajax call will only load the content into it's own content pane.
I figured out that if I create the tabContentContainer div prior to the Ajax request, then the tab selector has a object to then hide when another tab opens. Then, once the Ajax response is loaded, the visibility of it has already been set. See below:
$("#tabcontent").append('<div id="c'+count+'" class="tabContentContainer"></div>');
$.ajax ({
url: report,
cache: false,
success: function(html) {
$("#loading").hide();
$("#c"+count+"").html(''+html+'');
},
error: function(x, status, error) {
$("#tabcontent").append('<div id="c'+count+'" class="tabContentContainer"><div class="alert alert-error" style="margin-top:70px;"><button type="button" class="close" data-dismiss="alert">×</button><strong>Don\'t worry… It\'s not you, it\'s us.</strong> We were unable to connect to your data and deliver results. We are looking into this now.</div></div>');
$.ajax ({
url: 'admin/error_notification.php',
type: "POST",
data:{
error: error
}
});
},
async:true
});
I have such a setup. You call the function below indicating what tab you're loading into. I make sure each new tab has a unique ID (UUID) and that the function gets that ID to load the page.
There is a snag, however - I have found that if the sub pages loaded contain javascript code, that needs to initialize objects internally to the page,
they may be confused by the fact that the page is 'hidden'. Sometimes when
I get back to the tab with such elements, I would find they have a 'small' size.
This function also store the data submitted to the backend, so that you easily can create a 'reload' button.
function LoadView(ident, view, data) {
var img = $('<img>', {
src : '/images/ajax-loading.gif'
});
$('#' + ident).html(img);
data.view = view;
data.viewid = ident;
// console.log(data);
$.ajax({
url : '/cgi-bin/browser.cgi',
data : data,
type : 'GET',
dataType : 'html',
timeout : 30000000,
success : function(result) {
$("#" + ident).html(result);
// set data on view
$("#" + ident).data('data', data);
},
error : function(xhr, status, error) {
var img = $('<img>', {
src : '/images/exclamation_micro.png'
});
$('#' + ident).html(img.html() + error);
// alert("Error processing request " + error);
},
timeout : function() {
var img = $('<img>', {
src : '/images/exclamation_micro.png'
});
$('#' + ident).html(img.html() + ' Timeout');
// alert("Timeout processing request");
}
});
}
function ReloadView(view, ident) {
// Retrieve the data for the view
var data = $('#' + ident).data('data');
// Reload the view
LoadView(ident, data.view, data);
}

JQtouch Ajax not able to send the same request twice

Im creating an app using JQ mobile, it has a list of items and you select one and it send the goes to another page that does the ajax request.the problem is that if I go back select a different item from the list and then go back to the first item and select it. it will not show the item again just the previously selected item.
here is my code
<div id="get">
<script>
$.ajax({
url: "http://s336087876.onlinehome.us/pmc/newapp/php/showCoupon.php?id=" + test,
cache: true,
success: function(data) {
$('.coupon').html(data);
},
// Error handler
error: function(req, status, err){
alert('not working');
}
});
</script>
Also here is a link so you can see what it is doing.
http://s336087876.onlinehome.us/pmc/newapp/html/
Try adding "cacheGetRequests: false" in initialization. for more info http://code.google.com/p/jqtouch/issues/detail?id=35

Resources