So I have this Javascript code:
function AddToStuff(somethingID) {
var stuffID = document.getElementById('StuffID').innerText;
alert("First Alert: " + stuffID);
if (stuffID == -1) {
document.getElementById('StuffID').innerText = 0;
stuffID = 0;
}
alert("Second Alert: " + stuffID)
StuffCallback.fire(somethingID, stuffID);
}
$(document).ready(function () {
initializeStuff();
});
var StuffCallback = $.Callbacks();
function initializeStuff() {
StuffCallback.add(function (somethingID, stuffID) {
$.ajax({
url: "pos/Stuff",
type: "GET",
traditional: true,
data: {
somethingID: somethingID,
stuffID: stuffID
},
success: function (result, textStatus, xhr) {
alert("Third Alert: " + stuffID);
var contentArea = $("#Stuff");
contentArea.html(result);
$("#Stuff").hide();
$("#Stuff").show({ duration: 250 });
}
});
});
}
And this C# code:
public ActionResult Stuff(int somethingID = 0, int stuffID = -1)
{
if (stuffID == -1)
{
//do something
}
else if (stuffID == 0)
{
//do something else
}
else
{
//do something else
}
}
return View();
}
}
The problem is that the C# method always has stuffID at -1 and so performs the first "if" case.
When the page loads and $(document).ready calls initializeStuff, the stuffID is -1, so it performs the first "if" case, as desired. Later, when AddToStuff() is called, because the user clicked on something, it reads in my element StuffID, which I have initialized to -1. The First Alert does display the -1. Then StuffID gets changed to 0 in the "if" inside AddToStuff() and the Second Alert does display the 0.
But then I have the Javascript function AddToStuff call the C# function again, but the goal is to have the second parameter (stuffID) be the 0 instead of the -1. And even the Third Alert will display a 0. But in the C# function, the stuffID is still -1.
I can't pass in the 0. Any help would be appreciated.
Note: I generalized my code into "something" and "stuff", but that part should be working fine - the functions call when I expect them to.
Suggestions:
Use fiddler or developer tools in your browser to see what is being passed to the server (0, or -1)?
The default value to Stuff(int somethingID = 0, int stuffID = -1) can also be causing the problem if the data received by the server is not correct.
Set the data type in your Ajax call dataType: 'json'
If you are using a GET request, make sure that you have set the data object correctly
If I comment all your JS code and just write
StuffCallback.fire(0, 5);
it works nicely, as it accepts 5. That means that your stuffID is not being recognized as int. What kind of a HTML element is it? I see you are using .innerText. As you are using jQuery already, why not use
var stuffID = $('#StuffID').val();
I have noticed your problem though. You have a typo.
getElementById('StuffID') and your p is called "stuffID". JS IS case sensitive, so it will be enough to fix that, but please use
<input type="hidden" ID="StuffID" value="#stuffID">
as that's proper HTML markup
Related
In my ASP.NET Core web application, one of my pages has a sequence of steps that it performs to call stored procedures. Depending on whether or not stored procedures return rows, I route to one of two controller actions (either rendering a partial including an additional input, or overriding what that input would do and just coming back to the page on the next step).
Right now I've got code that is nearly there. My controller actions navigate and process correctly and my Ajax works... Sort of.
Button in the Razor view that calls the Ajax function
<input type="button" value="Run Check" onclick="runCheck('#actionItem.StepID', '#Model.Client.DatabaseConnectionString', '#Model.Client.ClientID')" />
Ajax
<script type="text/javascript">
function runCheck(x, y, z) {
$.ajax({
url: '#Url.Action("ProcessFeedbackHasRows", "Client")',
type: 'POST',
data: { stepId: x, databaseConnectionString: y, clientId: z },
success: function (result) {
if (result) {
alert('true');
var stepId = x;
var databaseConnectionString = y;
var clientId = z;
var url = '#Url.Action("ViewProcessingFeedBackPartial", "Client")';
$("#processingFeedbackPartialDiv").load(url, { stepId, databaseConnectionString, clientId },
function () {
$("#confirmButton").removeAttr("style");
});
} else {
alert('false');
var newUrl = '#Url.Action("Processing", "Client")';
window.location = newUrl;
}
}
});
};
</script>
Controller Action
public JsonResult ProcessFeedbackHasRows(int StepId, string DatabaseConnectionString, int ClientID)
{
bool hasRows = true;
FeedbackDetails feedbackDetails = new FeedbackDetails();
feedbackDetails.Data = _clientProcessingService.GetProcessingFeedbackDetails(StepId, DatabaseConnectionString);
if (feedbackDetails.Data.Rows.Count == 0)
{
_clientProcessingService.RunProcessStepConfirmation(DatabaseConnectionString, StepId, ClientID, "No information returned, automatically proceeding to next step.");
hasRows = false;
}
return new JsonResult (new { HasRows = hasRows });
}
The alerts are there to just prove that the right condition was in fact met and that the right things are happening. And this is where my problems lie. When I had the Network traffic tab of the F12 tools open, I noticed that whatever json object is created first determines all future runs of the code.
For example: let's say I forced the first item to come through with at least 1 row returned, I'd see the alert true, see the JSON object in the Network tab contain true and see my partial view, as expected.
The next several steps would produce a a false result because no rows were returned from the SP in the controller. The bool in the controller would be set to false, the JSON object in the Network tab would say HasRows = false, but my alert would show true and the partial still renders asking me for confirmation. So despite not returning any rows and producing a false result, I see the alert true and the partial is rendered even though in my Network tab I see
The opposite is true as well. If I had the first item through create an object where HasRows = false, and the next several would have been true, subsequent steps return true in the Network tab, but alert false and go through the false logic in the Ajax.
What is the best way to handle this? Is there a way to clear the JSON or something? I figured by creating a new JsonResult at the end of every method call, it would produce a new result to inspect, but it seems to continue using the first one sent in despite being able to see the others in the Network tab.
What I've tried
Disabling cache in Ajax by adding cache: false, right above the URL in the $.ajax setup.
Resetting the json object within the function after my else braces
result = []; and delete result.hasRows;
Despite these attempts, the ajax will always alert and go through whatever logic flow was sent first while the actual object contains the correct variable.
I actually solved this because in my inexperience with javascript and jQuery, I didn't understand exactly how the logic was being handled since I can't very easily debug the javascript the way I can the C#.
Through trial and error and alerts, I found that essentially, the in my Ajax I had to change the if condition to inspect result.hasRows rather than just the result.
<script type="text/javascript">
function runCheck(x, y, z) {
$.ajax({
cache: false,
url: '#Url.Action("ProcessFeedbackHasRows", "Client")',
type: 'POST',
data: { stepId: x, databaseConnectionString: y, clientId: z },
success: function (result) {
if (result.hasRows) {
alert('result = true');
alert('result.hasRows = ' + result.hasRows);
var stepId = x;
var databaseConnectionString = y;
var clientId = z;
var url = '#Url.Action("ViewProcessingFeedBackPartial", "Client")';
$("#processingFeedbackPartialDiv").load(url, { stepId, databaseConnectionString, clientId },
function () {
$("#confirmButton").removeAttr("style");
});
} else {
alert('result = false');
alert('result.hasRows = ' + result.hasRows);
var newUrl = '#Url.Action("Processing", "Client")';
window.location = newUrl;
}
}
});
};
</script>
The initial question still stands though. Assuming I wanted to delete the entire JSON object and use my initial logic present in the question, how can I clear or delete the entire object so that every time I hit that Ajax call, a new object would be inspected? Or is that now how this works and I solved the problem correctly?
Here i am trying to open the file in new tab by calling ViewFile action of Doctor controller using Ajax Success which is in functionabc(this) on click of anchor tag.
Now the problem is that everything is as required but the url doesnot open in new tab.
Below is my Ajax
<script>
function abc(thisEvent) {
debugger;
var getDoCredId = $(thisEvent).attr('docCredId');
var parameter = { id: getDoCredId };
$.ajax({
url: "/Doctor/ViewFile1",
type: "get",
dataType: "html",
data: parameter,
success: function (data) {
debugger;
if (data = true) {
debugger;
var getdoctorId = $(thisEvent).attr('docCredId');
var url = "/Doctor/ViewFile/" + getdoctorId;
window.open(url, "_blank");
}
else {
debugger;
showNotification("Error", "warning");
}
}
});
}
Below is my anchor tag HTML
<a title="View Attachment" docCredId = "' + getDocCredId + '" onclick="abc(this)"><i class="btn btn-web-tbl btn-warning fa fa-eye "></i></a>
Below is code behind
public bool ViewFile1(int id)
{
var document = _doctorService.GetDoctorCredentialDetails(id);
string AttachPath = ConfigPath.DoctorCredentialsAttachmentPath;
string strFileFullPath = Path.Combine(AttachPath, document.AttachedFile);
string contentType = MimeTypes.GetMimeType(strFileFullPath);
bool checkFileInFolder = System.IO.File.Exists(strFileFullPath);
if (checkFileInFolder == true)
{
return true;
}
else
{
return false;
}
}
public ActionResult ViewFile(int id)
{
var document = _doctorService.GetDoctorCredentialDetails(id);
string AttachPath = ConfigPath.DoctorCredentialsAttachmentPath;
string strFileFullPath = Path.Combine(AttachPath, document.AttachedFile);
string contentType = MimeTypes.GetMimeType(strFileFullPath);
bool checkFileInFolder = System.IO.File.Exists(strFileFullPath);
bool filedata = System.IO.File.ReadAllBytes(strFileFullPath).Any();
byte[] filedata1 = System.IO.File.ReadAllBytes(strFileFullPath);
var cd = new System.Net.Mime.ContentDisposition
{
FileName = document.FileName,
Inline = true
};
Request.HttpContext.Response.Headers.Add("Content-Disposition", cd.ToString());
return File(filedata1, contentType);
}
Since this is too long for a regular comment, I am posting this as an answer, although it isn't directly going solve the problem because I am not able to reproduce it, but might give some insights and let you check the differences with what happens in your code as compared with this simplified example.
Calling window.open() from jQuery ajax success callback works just fine: https://codepen.io/nomaed/pen/dgezRa
I used the same pattern as you did, without your server code but using jsonplaceholder.typicode.com sample API instead.
There are some issues with the code sample that you might want to consider, even though you didn't ask for comments about it and it's not directly related to your issue (probably):
if (data = true) means data will always be true. You probably mean to do a if (data === true) if you know it's a boolean value, or if (data) if you want to accept any truthy value (true, {}, "something", 42, etc). Judging by the Java code and how you define the response format in the jQuery ajax call, it looks like you're expecting the "data" variable result be an HTML and not a boolean. You might want to try and remove the dataType: "html" row and let jQuery set the data format according to what is coming back from the server, and/or send a JSON formatted response, as in a POJO of { result: true } for a successful response. Then make sure that data.result === true to be sure that you got what you expect.
You should probably add arbitrary data to tags DOM elements the data-* attributes and if you're using jQuery, access them using the .data() selector. White adding just random attributs with string values may work, it's considered an abuse of the HTML and DOM, and the data-* attributes are there specifically for adding any data.
In the abc() function you grab the value of the attribute in the beginning (var getDoCredId = $(thisEvent).attr('docCredId');) but in the callback you're trying to get the value once more. You really don't need it since the success() callback is a closure in the scope of the abc() function and it has access to the value already, so doing var getdoctorId = $(thisEvent).attr('docCredId'); in the callback is really not needed.
I'd also suggest naming getDoCredId variable just as docCredId. Having a "get" prefix usually means that it's a getter function or a reference to some getter. Likewise, the "thisEvent" argument of the main function should probably be called "callerElement" or something like that since it's not an event, it's an actual element that you're passing directly from the DOM when calling abc(this) in the onClick event handler of the <a> anchor. This is just to make the code clearer to understand for anyone who's reading it, and for yourself when you're coming back to it several months in the future and trying to figure out what's going on :)
Try adding async: false to your Ajax request
function abc(thisEvent) {
debugger;
var getDoCredId = $(thisEvent).attr('docCredId');
var parameter = { id: getDoCredId };
$.ajax({
async: false, // <<<----------- add this
url: "/Doctor/ViewFile1",
type: "get",
dataType: "html",
data: parameter,
success: function (data) {
debugger;
if (data = true) {
debugger;
var getdoctorId = $(thisEvent).attr('docCredId');
var url = "/Doctor/ViewFile/" + getdoctorId;
window.open(url, "_blank");
}
else {
debugger;
showNotification("Error", "warning");
}
}
});
}
I am developing a web page which displays an alert as soon as somebody inserts a new tuple in a database table using the same 'mesa' column that I sent in my AJAX request, so for that purpose I created a Javascript Timer in which I am constantly sending AJAX requests to check if there is a new tuple in my database table and so far the timed AJAX request are working, but when I want to condition the response with an if to see if the value of it equals to a certain value, it just completely skips it, so I am unable to display alerts even if the values that the AJAX response requests are throwing are right, so I was wondering what I could be doing wrong, I have been analyzing the code for over 2 hours and I don't seem to find the error, I even displayed alerts to verify that the response is equal to 0 or 1 which showed up that they do display them right, and I used response.responseText too , any help would he highly appreciated, thank you so much.
This is my Javascript file
var Solicitud_Comandas = [];
for (var k = 1; k <= 15; k++) {
Solicitud_Comandas[k] = SolicitudComanda(k);
if(!sessionStorage.getItem("rm"+k))
{
sessionStorage.setItem("rm"+k,false);
}
}
function SolicitudComanda(k)
{
return function() {
$(document).ready(function()
{
$.ajax({
type: "POST",
url: "Consultar_Comandas_Pendientes.php",
data: {mesa : k},
complete: function (response, TextStatus)
{
MensajeAlerta(response,k);
},
fail: function (resultado,TextStatus)
{
alert("it didn't work because... " + resultado+ " " +TextStatus);
}
});
});
}
}
function MensajeAlerta(response,m)
{
if(response == 0 )
{
sessionStorage.removeItem("rm"+m);
sessionStorage.setItem("rm"+m,false);
}
else if (response == 1)
{
if(sessionStorage.getItem("rm"+m) == "false")
{
alert("Hay una comanda pendiente en la mesa "+m);
sessionStorage.removeItem("rm"+m);
sessionStorage.setItem("rm"+m, true);
}
}
}
Temporizador= setInterval(SolicitudDeComanda,2500);
function SolicitudDeComanda()
{
$(document).ready(function(){
for (var l =1; l<= 15; l++) {
Solicitud_Comandas[l]();
};
});
}
And this is the Consultar_Comandas_Pendientes.php
<?php
require "Conexion.php";
$NumeroMesa = $_POST["mesa"];
$Platillos = 0;
$filas = false;
$SelectionRows = "SELECT * FROM comandapendiente WHERE mesa = '$NumeroMesa'";
$rows = mysqli_query($con,$SelectionRows);
while($reg = mysqli_fetch_array($rows))
{
if(isset($reg["id"]))
{
$filas = true;
$Platillos++;
}
}
if ($filas == true)
{
echo true;
}
else
{
echo false;
}
mysqli_close($con);
?>
As you can see, if there is a new tuple, the AJAX response is going to be equal to either true or false which is what I question on the if statements in the Javascript code.
The first issue you have is caused by using the $.ajax({ ... complete: property and assuming the first argument to the callback is your data. But it is not, it is the request object (see documentation). Use success: instead of complete: and then you get the data as first argument to your callback function.
The second issue you have is caused by the PHP line:
echo false;
This does not echo anything, because in PHP when false needs to be converted to string, it becomes the empty string, unlike in other languages, where it becomes "0" or "false".
So you should better echo literal strings in PHP, like:
echo "1";
and
echo "0";
Also, make sure PHP does not output anything else than just that 0 or 1. Specifically check that there are no blanks, tabs, empty lines... etc, before the <?php tag or after the ?> tag. If you have several such opening and closing tags, try to join them into one PHP block.
For the same reason, make sure to save your PHP in UTF-8 without BOM. The Byte Order Mark is a three character sequence that is sometimes saved at the start of a file, in order to declare the character encoding as UTF-8. But this sequence would then also be part of the response. Most editors have an option to save with or without BOM.
Some remarks on your code
It is a bit strange to see $(document).ready(...) inside other functions. Although this works fine, it is not usually done this way. Normally there is no reason to have it inside another function. All is OK, if you use it once, at this position only:
$(document).ready(function(){
Temporizador= setInterval(SolicitudDeComanda,2500);
});
I would write false as a string when writing to local storage:
sessionStorage.setItem("rm"+k, "false");
It works fine without the quotes, but you then rely on the fact that JavaScript converts it to that string. I believe your code looks better with "false" written as a string explicitly.
Also, it seems unnecessary to call removeItem() if you are doing a setItem() right after it. setItem() overwrites any existing value with the same key.
In your tests on the response data, it would make more sense to do string comparisons, since the data returned by PHP will be string. So like:
if(response == "0")
... and add an else to catch any unexpected value (other than "0" or "1") so you are made aware of it (via alert or something).
If you have trouble with some unexpected characters preceding the value 0 or 1, and you can't get rid of those by removing the BOM and any white space in your PHP file, then there is a work-around by relaxing your test like this:
if (response.indexOf('0') !== -1)
It is also better to specify the dataType: 'text' option in your ajax call, so not to leave that to jQuery to guess.
I have the code bellow running in a .each function. However when all is set and done and i do alert(inserted); or alert of any other variable they come out 0 which is what i have them set as when i declare them. I am sure they are within scope. I have a feeling this has to do with the timing of the ajax because if i put an alert after each call, the counter system works. Any thought? Also I am sure that the proper if statements are called as I attached alerts (as i said above which when i do this the counter works) and they fire properly AND no error codes as brought up from the consol.
$.ajax({
type: "POST",
url: "/php/filename.php",
data: {
one: $('#1').val(),
two: $('#2').val(),
three: $('#3').val(),
four: $('#4').val(),
five: $('#5').val(),
six: $('#6').val(),
seven: $('#classlist').val(),
id: $('#7').html()
}
}).done(function(msg) {
if (msg == "inserted") {
inserted++;
}
else if (msg == "updated") {
updated++;
}
else if (msg == "duplicate") {
duplicate++;
}
else if (msg == "0") {
fail++;
}
});
Ajax is asynchronous, your alert is happening before the ajax is complete. Store all of your ajax return values in an array, pass them all to .when, and then use it's done to alert the value of your variable.
var promiseArr = [], inserted = 0;
for (var i = 0; i < 30000; i++) { // <--- unrealistic number of iterations
promiseArr.push($.ajax({url:"foo.php?id=" + i}).done(function(){
inserted++;
}));
}
$.when.apply($,promiseArr).done(function(){
alert(inserted);
});
I learn jQuery and don't understand this situation:
When running this code in debug mode all work well. But when running this code normal, calback function don't starts. Why?
In non debug mode I have -> "Start" -> "End 10"
Browser: Google Chrome.
var nrPost = 10;
$("#buttnX").click(function() {
alert("Start");
GoPosts();
End();
});
function End() {
alert('End ' + nrPost);
};
function GoPosts() {
$.ajaxSetup({async:false});
var url = "http://......";
var data = { ... };
$.post(url, data, Callback, 'json');
};
function Callback(response) {
if (response.error) {
return;
}
nrPost--;
if (nrPost > 0) [
GoPosts();
} else {
return;
}
};
You had an extra }; in your code. I changed it around a bit to use jQuery and put it up on jsfiddle.
http://jsfiddle.net/rH8RV/19/
It should alert: "Start" and then "End 10", that's correct based on how you wrote your code. Were you expecting anything else?
I don't know what you're planning to do with your recursive implementation, but if that's all, you could actually do this:
function startLoop(nrPost) {
// No need to put this in a loop
$.ajaxSetup({ async: false });
for (var i = 0; i < nrPost; i++) {
alert('Start ' + i);
var url = 'http://......';
var data = {};
$.post(url, data, function (response) {
if (response.error)
return;
alert('End ' + i);
}, 'json');
}
}
$('#buttnX').click(function () { startLoop(10) });
Hope that helps!
I imagine you are expecting the display to be:
"Start"
"End 0"
This is unlikely to work with your solution.
Your Ajax call $.post(url, data, Callback, 'json'); is asynchronous. This means that once the $.post method returns, the request is sent to the URL you have provided. However, Callback is not called until JQuery receives the answers. What happens immediately is that GoPosts terminates and the program continues. It comes back to line 5 of your code, inside the anonymous function in your click handler. At that point, End() is called and alerts "End 10".
You probably want to put your call to End in Callback instead:
function Callback(response)
{
if (response.error)
{
return;
}
nrPost--;
if(nrPost>0)
GoPosts();
else
{
End(); // You only want to end once you have made you nrPost calls to GoPost
return;
}
};