AJAX call not firing from inside if statement - javascript

I have the following code. There is a button in the UI that when clicked executes the if statement. I pass in a URL from a database and compare it to the current URL the user is on. If they match I want to run the code below, else I want to open the correct tab then run the code below.
With this code below I mean everything below starting from $('#sceanrioDropdownList').change(function () {...}. The code then checks a drop down and gets the selected Id from which an AJAX call is made to my web API that uses that Id in a stored procedure to return the results. The returned data is then iterated over and stored in variables which I am using to append to specific inputs, buttons and drop downs.
This is what I have so far and I think I have developed this correctly. The issue that I am currently having is that the UI wants everything from ... to be run if the if statement is true. I have tried CTRL+C and CTRL+V to copy the code into the if statement. I have also tried putting it in a new function and referencing that function n the if statement. Both do not work and I was using console.log to inspect the returned data.
It does however when I attempt to call it from inside i statement it doesn't return any data or error. It just doesn't seem to fire.
Is there a way in which I can achieve the functionality I desire? Do you have any suggestions as to if I have done something wrong. Thanks in advance.
$('#automate').click(automateButton);
function automateButton() {
if (webpageUrl == activeTabUrl) {
// do nothing
} else {
// Window opens
window.open(webpageUrl);
}
}
$('#scenarioDropdownList').change(function() {
var scenarioId = $('#scenarioDropdownList option:selected').prop('id');
getData(scenarioId);
});
function getData(scenarioId) {
$.ajax({
type: "GET",
url: 'http://localhost:54442/api/scenariodatas/GetScenarioData',
data: {
scenarioId: scenarioId
},
dataType: 'JSON',
success: scenarioData,
error: function() {
console.log("There has been an error retrieving the data");
}
});
}
function scenarioData(response) {
$.each(response, function(key, val) {
var fieldType = val.fieldType;
var fieldName = val.fieldName;
var fieldValue = val.fieldValue;
var field = $(fieldName);
if (field != undefined) {
switch (fieldType) {
case "Input":
$(field).val(fieldValue);
break;
case "Button":
$(field).click();
break;
case "Select":
$(field).val(fieldValue);
break;
}
}
})
}

onChange don´t work well with buttons because onChange detect a change in the value of your component, because of this, it´s highly recommended to use onClick when you use a button.
$('#scenarioDropdownList').click(function() {
var scenarioId = $('#scenarioDropdownList option:selected').prop('id');
getData(scenarioId);
});
I recommend you to put alerts when you are trying to test this sort of JS
EJM:
$('#scenarioDropdownList').change(function() {
alert('button active');
var scenarioId = $('#scenarioDropdownList option:selected').prop('id');
getData(scenarioId);
});
this alert allow you to know if the code is firing or not

Related

ajax call causing fits with hiding a modal

EDIT: Found an un-elegant solution here:
How do I close a modal window after AJAX success
using location.reload(), though I have to say that I think there is a bug in the modal handling in jquery. I do not think my code below was wrong yet it doesn't work. :(
When a user clicks a button it calls a method :
onClick(GroupInformationDialog(true)) ... etc
So that calls a method to see if we should hide or open a modal first based on what is passed and second based on what the result of another method that does an ajax call has:
function GroupInformationDialog(open) {
if (open) {
if (GetProviderInfo() == true) {
$("#groupinfo-dialog").modal("show");
} else {
// we got no real data so let's not show the modal at all
$("#groupinfo-dialog").modal("hide");
}
} else {
$("groupinfo-dialog").modal("hide");
}
return false;
}
and the ajax call:
function GetProviderInfo() {
event.preventDefault();
gid = $('#group_info option:selected').val()
pid = $("#provider_id").val()
$.ajax({
url: '{% url 'ipaswdb: get_group_info_data' %}',
data: "group_id=" + gid + "&prov_id=" + pid,
success: function (resp) {
if (resp['response'] == 'NOGROUP') {
alert("You must first select a group");
$("groupinfo-dialog").modal('hide'); //arg this doesn't work either
return false;
}
else if (resp['response'] == 'OK') {
//fill out form with data.
$("#gi_date_joined_group").val(resp['date_joined_group']);// = resp['credentialing_contact'];
$("#gi_provider_contact").val(resp['provider_contact']);
$("#gi_credentialing_contact").val(resp['credentialing_contact']);
return true;
}
else {
$("#gi_date_joined_group").val('');// = resp['credentialing_contact'];
$("#gi_provider_contact").val('');
$("#gi_credentialing_contact").val('');
return true;
}
}
});
}
The problem is, the return true, or false in GetProviderInfo() is ignored, it is like GroupInformationDialog is evaluated all the way before GetProviderInfo is, so the result is a modal dialog that always pops up.
I even tried to have the
$("#groupinfo-dialog").modal('hide');
in the if(resp['response']=='NOGROUP') code section, with no dice.
It is almost like I need a wait function, I thought success was a call back function was going to take care of it, but alas it did not.
You're mixing synchronous and async code here; you can't synchronously use if (GetProviderInfo() == true) since what you want to return from that function depends on an asynchronous ajax call.
The return statements you currenty have will go to the success handler they're contained within; they will not set the return value for getProviderInfo itself. By the time that success handler runs, getProviderInfo has already returned.
You could have that function return a promise (using return $.ajax({...})) and have the caller handle the results asynchronously -- but it looks like in this case it might be simpler to just hide / show the modal from within the ajax call's success handler. (It looks like the sole reason that isn't working currently is just a typo: there are a couple spots where you have $("groupinfo-dialog") when you mean $("#groupinfo-dialog")

JQuery $.post callback firing a function that never finishes

Here's the problem. I'm making a callback to the server that receives an MVC partial page. It's been working great, it calls the success function and all that. However, I'm calling a function after which iterates through specific elements:
$(".tool-fields.in div.collapse, .common-fields div.collapse").each(...)
Inside this, I'm checking for a specific attribute (custom one using data-) which is also working great; however; the iterator never finishes. No error messages are given, the program doesn't hold up. It just quits.
Here's the function with the iterator
function HideShow() {
$(".tool-fields.in div.collapse, .common-fields div.collapse").each(function () {
if (IsDataYesNoHide(this)) {
$(this).collapse("show");
}
else
$(this).collapse("hide");
});
alert("test");
}
Here's the function called in that, "IsDataYesNoHide":
function IsDataYesNoHide(element) {
var $element = $(element);
var datayesnohide = $element.attr("data-yes-no-hide");
if (datayesnohide !== undefined) {
var array = datayesnohide.split(";");
var returnAnswer = true;
for (var i in array) {
var answer = array[i].split("=")[1];
returnAnswer = returnAnswer && (answer.toLowerCase() === "true");
}
return returnAnswer;
}
else {
return false;
}
}
This is the way the attribute appears
data-yes-no-hide="pKanban_Val=true;pTwoBoxSystem_Val=true;"
EDIT: Per request, here is the jquery $.post
$.post(path + conPath + '/GrabDetails', $.param({ data: dataArr }, true), function (data) {
ToggleLoader(false); //Page load finished so the spinner should stop
if (data !== "") { //if we got anything back of if there wasn't a ghost record
$container.find(".container").first().append(data); //add the content
var $changes = $("#Changes"); //grab the changes
var $details = $("#details"); //grab the current
SplitPage($container, $details, $changes); //Just CSS changes
MoveApproveReject($changes); //Moves buttons to the left of the screen
MarkAsDifferent($changes, $details) //Adds the data- attribute and colors differences
}
else {
$(".Details .modal-content").removeClass("extra-wide"); //Normal page
$(".Details input[type=radio]").each(function () {
CheckOptionalFields(this);
});
}
HideShow(); //Hide or show fields by business logic
});
For a while, I thought the jquery collapse was breaking, but putting the simple alert('test') showed me what was happening. It just was never finishing.
Are there specific lengths of time a callback function can be called from a jquery postback? I'm loading everything in modal views which would indicate "oh maybe jquery is included twice", but I've already had that problem for other things and have made sure that it only ever includes once. As in the include is only once in the entire app and the layout is only applied to the main page.
I'm open to any possibilities.
Thanks!
~Brandon
Found the problem. I had a variable that was sometimes being set as undefined cause it to silently crash. I have no idea why there was no error message.

Creating ajax request loop within an 'each' function

This topic is covered in a few other questions, but I had some difficulty applying the suggested approaches into this use case. I have a checkbox list, where a user can select n sub-sites to publish their post to. since this list could grow to be 100+, I need an efficient way to perform an expensive task on each one. It's okay if it takes awhile, as long as Im providing visual feedback, so I planned to apply an "in progress" style to each checkbox item as its working, then move to the next item int he list once it is successfully published. Also note: I'm working in the WordPress wp_ajax_ hook but the PHP side of things is working well, this is focused on the JS solution.
This code is working right now (console.logs left in for debug), but I've seen multiple warnings against using async: true. How can I achieve a waterfall AJAX loop in a more efficient way?
//Starts when user clicks a button
$("a#as_network_syndicate").click( function(e) {
e.preventDefault(); //stop the button from loading the page
//Get the checklist values that are checked (option value = site_id)
$('.as-network-list').first().find('input[type="checkbox"]').each(function(){
if($(this).is(':checked')){
blog_id = $(this).val();
console.log(blog_id+' started');
$(this).parent().addClass('synd-in-progress'); //add visual feedback of 'in-progress'
var process = as_process_syndication_to_blog(blog_id);
console.log('finished'+blog_id);
$(this).parent().removeClass('synd-in-progress');
}
});
});
function as_process_syndication_to_blog(blog_id){
var data = {
"post_id": $('#as-syndicate_data-attr').attr("data-post_id"), //these values are stored in hidden html elements
"nonce": $('#as-syndicate_data-attr').attr("data-nonce"),
"blog_id": blog_id
};
var result = as_syndicate_to_blog(data);
console.log('end 2nd func');
return true;
}
function as_syndicate_to_blog(data){
$.ajax({
type : "post",
dataType : "json",
async: false,
url : ASpub.ajaxurl, //reference localized script to trigger wp_ajax PHP function
data : {action: "as_syndicate_post", post_id : data.post_id, nonce: data.nonce, blog_id: data.blog_id},
success: function(response) {
if(response.type == "success") {
console.log(response);
return response;
} else {
}
},
error: {
}
});
}
Indeed, doing synchronous AJAX request is bad because it will block the browser during the whole AJAX call. This means that the user cannot interact with your page during this time. In your case, if you're doing like 30 AJAX calls which take say 0.5 seconds, the browser will be blocked during 15 whole seconds, that's a lot.
In any case, you could do something following this pattern:
// some huge list
var allOptions = [];
function doIntensiveWork (option, callback) {
// do what ever you want
// then call 'callback' when work is done
callback();
}
function processNextOption () {
if (allOptions.length === 0)
{
// list is empty, so you're done
return;
}
// get the next item
var option = allOptions.shift();
// process this item, and call "processNextOption" when done
doIntensiveWork(option, processNextOption);
// if "doIntensiveWork" is asynchronous (using AJAX for example)
// the code above might be OK.
// but if "doIntensiveWork" is synchronous,
// you should let the browser breath a bit, like this:
doIntensiveWork(option, function () {
setTimeout(processNextOption, 0);
});
}
processNextOption();
Notice: as said by Karl-André Gagnon, you should avoid doing many AJAX requests using this technique. Try combining them if you can, it will be better and faster.
If you can't pass the whole block to the server to be processed in bulk, you could use a jQuery queue. This is using your sample code as a base:
var $container = $('.as-network-list').first();
$container.find('input[type="checkbox"]:checked').each(function(){
var $input = $(this);
$container.queue('publish', function(next) {
var blog_id = $input.val(),
$parent = $input.parent();
console.log(blog_id+' started');
$parent.addClass('synd-in-progress'); //add visual feedback of 'in-progress'
as_process_syndication_to_blog(blog_id).done(function(response) {
console.log(response);
console.log('finished'+blog_id);
$parent.removeClass('synd-in-progress');
next();
});
});
});
$container.dequeue('publish');
function as_process_syndication_to_blog(blog_id){
var data = {
"post_id": $('#as-syndicate_data-attr').attr("data-post_id"), //these values are stored in hidden html elements
"nonce": $('#as-syndicate_data-attr').attr("data-nonce"),
"blog_id": blog_id
};
return as_syndicate_to_blog(data).done(function(){ console.log('end 2nd func'); });
}
function as_syndicate_to_blog(data){
return $.ajax({
type : "post",
dataType : "json",
url : ASpub.ajaxurl, //reference localized script to trigger wp_ajax PHP function
data : {action: "as_syndicate_post", post_id : data.post_id, nonce: data.nonce, blog_id: data.blog_id}
});
}
I don't have a test environment for this so you may need to tweak it for your use case.

AJAX GET Call Will work on the first call but not after other clicks

I have an ajax call in my javascript that returns and loads a partial view into a div. This function used to work but then all the sudden it stopped. I do not think I changed any code or anything that would cause issue but obviously something is going on. The Ajax call will work on the first time when you click on the button in which it is called but never again until you reload the page. I have tried adding more parameters and moving the javascript around but it still did not work. Is there any reason why this could happen?
I have tried moving the javascript out of the onOpen event and the same thing still happens. I have also put an alert call to make sure it is getting to the success call and the alert is called. I have also installed fiddler to check the call and the call is never made except on the first click of the button. This is a very frustrating error and all help is much appreciated.
Here is my Javascript:
#section scripts
{
<script type="text/javascript">
$(document).ready(function () {
$("#assets-button").on("click", function ()
{
$('#assets-container').bPopup(
{
modal: true,
onOpen: function () {
$.ajax({
type: 'GET',
url: '#Url.Action("EmployeeAssets", "Employee",new { id = Model.ID, empNo = Model.EmployeeNumber, username = Model.UserName })',
success: function (data) {
$('#assets-container').html(data);
}
});
},
onClose: function () {
var f = $('#assets-container').children('form');
var serializedForm = f.serialize();
var action = '#Url.Action("EmployeeAssets","Employee",new {empNo = Model.EmployeeNumber})';
$.post(action, serializedForm);
}
});
});
});
</script>
}
Here is the action that I am trying to call:
[HttpGet]
public ActionResult EmployeeAssets(int id, int empNo, string username = null)
{
var assets = _employeeDb.EmployeeAssets.FirstOrDefault(e => e.EmpNo == empNo);
if (assets == null)
{
var firstOrDefault = _employeeDb.EmployeeMasters.FirstOrDefault(e => e.EmployeeNumber == empNo);
if (firstOrDefault != null)
{
username = firstOrDefault.UserName;
}
var newasset = new EmployeeAsset()
{
EmpNo = empNo,
UserName = username
};
_employeeDb.EmployeeAssets.Add(newasset);
_employeeDb.SaveChanges();
assets = newasset;
}
return PartialView(assets);
}
You may try using the cache property of the settings object you are passing to the AJAX call. According to the jQuery documentation for .ajax the default for cache is set to true, so I wonder whether your browser is accessing a cached copy of the result after the first request. Looks like you could also set the dataType, and that will default the cache back to false.
Also, I would suggest putting your alert inside of the onOpen event handler in addition to the success handler just to be sure that's also being called. So that may help you debug a bit further.

Jquery simple function

The aim of this code is to delete a comment with AJAX. The function is called as follows:
DeleteComment(166);
And the code that runs is:
// Each delete button
function DeleteComment(CommentID) {
$.ajax({
url: AJAXURL + "?action=del&id=" + CommentID,
success: function (data) {
// Parse the data
if (data.substring(0, 1) == "1") {
$('#cid' + CommentID).hide();
} else {
alert(data.substring(2, data.length));
}
}
});
}
However the $('#cid' + CommentID).hide(); line never fires as CommentID isn't retained, I'm new to Jquery, could someone show me how to change this so the comments ID is retained when the ajax success is called?
put the $('#cid' + CommentID).hide(); before $.ajax({ and then add $('#cid' + CommentID).show(); to your else condition..
Hide it first and then reshow it if deletion fails...
Not the most graceful solution, but the path of least resistance from where you are.
Can you post more of the surrounding code? As is, your code looks like it should work. But I see a troublesome comment: // Each delete button. The way you are binding the DeleteComment function to the buttons must not be working the way you assume.
Try this instead:
// Iterate over each delete button.
// The .each(...) provides you a function, a.k.a. local scope, for each button.
$(".deleteButtons").each(function (idx, el) {
// This is very important: you must create a local variable to hold the ID.
// How to get the ID is up to you.
var id = getTheCorrespondingCommentId(idx, el);
// Now you can safely pass the local variable to the DeleteComment function:
$(el).click(function() { DeleteComment(id); });
});

Categories