how to return ajax suceess from user defined function [duplicate] - function

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
I am having the bellow function .
Here i want to return ajax success from user defined function . How to do this
alert(Ajaxcall(id_array,"del"));
function Ajaxcall(id_array,type){
$.ajax({
type: "POST",
url: "serverpage.php",
cache:false,
data: ({id:id_array,type:type}),
success: function(msg){
return msg; //this returns nothing
}
});
alert(msg); // this one undefined
}
thanks

The "a" in "ajax" stands for "asynchronous" ("Asynchronous JavaScript And XML", although these days most people use it with JSON rather than XML).
So your Ajaxcall function returns before the ajax call completes, which is why you can't return the message as a return value.
The usual thing to do is to pass in a callback instead:
Ajaxcall(id_array,"del", functon(msg) {
alert(msg);
});
function Ajaxcall(id_array,type, callback){
$.ajax({
type: "POST",
url: "serverpage.php",
cache:false,
data: ({id:id_array,type:type}),
success: function(msg){
callback(msg);
}
});
}
It's surprisingly easy with JavaScript, because JavaScript's functions are closures and can be defined inline. So for instance, suppose you wanted to do this:
function foo() {
var ajaxStuff, localData;
localData = doSomething();
ajaxStuff = getAjaxStuff();
doSomethingElse(ajaxStuff);
doAnotherThing(localData);
}
you can literally rewrite that asynchronously like this:
function foo() {
var localData;
localData = doSomething();
getAjaxStuff(function(ajaxStuff) {
doSomethingElse(ajaxStuff);
doAnotherThing(localData);
});
}
I should note that it's possible to make an ajax call synchronous. In jQuery, you do that by passing the async option in (setting it false). But it's a very bad idea. Synchronous ajax calls lock up the UI of most browsers in a very user-unfriendly fashion. Instead, restructure your code slightly as above.
But just for completeness:
alert(Ajaxcall(id_array,"del"));
function Ajaxcall(id_array,type){
var returnValue;
$.ajax({
type: "POST",
url: "serverpage.php",
cache:false,
async: false, // <== Synchronous request, very bad idea
data: ({id:id_array,type:type}),
success: function(msg){
returnValue = msg;
}
});
return returnValue;
}

JQuery has a number of global Ajax event handlers, including $.ajaxComplete() and $.ajaxSuccess() (ref: http://api.jquery.com/ajaxSuccess/).
The code can be attached to any DOM element and looks like this:
/* Gets called when all request completes successfully */
$("#myElement").ajaxSuccess(function(event,request,settings){
$(this).html("<h4>Successful ajax request</h4>");
});
This code will execute whenever any successful Ajax call is completed.

Related

Append additional HTML result in calling MVC action by Ajax in DNN8

I'm new in DNN development.
I have created a very simple module in Visual studio--- A textbox and a button.
I just want to call the action in a controller by click the button, then show the return result in the textbox.
The code call the action success, but not sure why append lots of HTML inforation in the result.
Here is the action in the controller:
public ActionResult test1()
{
return Content("Return something");
}
Here is the Ajax code from the View:
$(document).ready(function () {
$("#btnSub").click(function () {
//alert(this.action);
$.ajax({
type:"GET",
contentType:"application/text",
url: "#Url.Action("test1", "Sky")",
data:"",
dataType: "text",
success: function (data) { $("#txtResult").val(data); alert("Success!") },
error:function(){alert("Failed!")}
});
});
});
And here is the result show in the textbox:
Anyone can let me know why the HTML information returned? Actually, I don't need it.
Thanks
Unfortunately, as described in DNN8 MVC unsupported features, it's not yet possible to return a JsonResult. So the solution I used is to return an ActionResult (although the function returns Json):
public ActionResult Test()
{
return Json(new { success = true });
}
On jquery side, I setup ajax call to receive result as html. This avoid the browser to display a parsing error. Finally, just need to remove the html part and manually parse the response. It's not very clean, but the only solution I found until DNN support JsonResult.
$.ajax({
url: '#Url.Action("Index", "Contact")',
type: 'POST',
dataType: 'html',
data: $('#contact-form input').serialize(),
success: function (response) {
jsonPart = response.substring(0, response.indexOf("<!DOCTYPE html>"));
var data = JSON.parse(jsonPart);
if (data.success) {
alert("Great");
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert("Error!");
}
});
EDIT : Improved solution
DNN8 now support IMvcRouteMapper. You can then register a route in RouteConfig.cs. Once done, you can call the function using following URL :
/DesktopModules/MVC/ModuleName/Controller/Action
The action can return a JsonResult. But pay attention, if you just call that function, it will fail with a null exception on ModuleContext. You have to include in the ajax call the following header :
headers: {
"ModuleId": #Dnn.ModuleContext.ModuleId,
"TabId": #Dnn.ModuleContext.TabId,
"RequestVerificationToken": $("input[name='__RequestVerificationToken']").val()
}
You can find the module complete code here.
This is a working ajax call in DNN 9. You dont have to use #urlaction it will give whole html as well as data. dnn.getVar("sf_siteRoot", "/") +
"DesktopModules/MVC/ModuleName/Controller/Action", this does the trick and don't forget to add the header otherwise it will throw 500 error.
$.ajax({
url: dnn.getVar("sf_siteRoot", "/") +
"DesktopModules/MVC/ModuleName/Controller/Action",
type: 'POST',
contentType: "application/json; charset=utf-8",
dataType: 'json',
data: "{ 'id':" + JSON.stringify(3543)+" }",
headers: {
"ModuleId": #Dnn.ModuleContext.ModuleId,
"TabId": #Dnn.ModuleCon`enter code here`text.TabId,
"RequestVerificationToken":
$("input[name='__RequestVerificationToken']").val()
},
success: function (response) {
debugger;
},
error: function (errmsg) {
alert("Error!");
}
});
Your controller should be
[HttpPost]
public ActionResult ActionName(int id)
{
var data = id;
return BuidJsonResult(true,data);
}
Happy Coding :)

Weird JSON, how to access needed value

This is the JSON response:
I need to access data[1], which is 0.2. How do I get it?
Here's the actual code:
function getTheValue(){
var result = $.ajax({ url: "https://www.blahblah.com/json" });
return result;
}
console.log(getTheValue());
Here's another way I tried, no luck:
var val = getTheValue();
console.log(val.responseJSON.dataset.data[0][1]);
Your getTheValue function is not returning the JSON response from the AJAX call. It is returning a promise object, since it is actually a doing an asynchronous call. I suggest you read documentation for jQuery.ajax() for more information.
Anyway, you can fix your problem by doing this:
var val;
getTheValue().done(function(response) {
val = response.dataset.data[0][1];
});
The response you're seeing is the ajax object, not the return from the function. $.ajax is asynchronous, so the value isn't available until immediately.
Adapted from the jQuery docs:
$.ajax({
url: your_url,
})
.done(function( result ) {
console.log( result );
});
will give you result. Your subsequent code will need to be triggered inside that done() function.
This finally helped me:
var tBill = getTheBill();
function getTheBill(){
var result;
$.ajax
({
url: "https://www.blahblah.com/json",
context: document.body,
async: false
}).done(function(val) {
result = val;
});
return result.dataset.data[0][1];
}
Guys, thanks for your help! jimm101, you rock.
That object isn't json in its common sense but an Javascript object, if you want the ajax result you have to use a callback:
$.ajax({
url: "https://www.blahblah.com/json" ,
dataType: "json",
})
.done(function(data) {
console.log(data);
});

Pass ViewModal from javascript file to code-behind

I have a Javascript file that calls a method in my code-behind. This seems to work if I create a parameterless default constructor, EXAMPLE 1, BUT I want to pass to the save method my ViewModel, EXAMPLE 2. When I do this I get a 500 error. After digging deeper I discovered more details about that network error.
Parameterless Default Constructor - this works but only if the other constructor is commented out.
EXAMPLE 1
[HttpPost]
public JsonResult SaveWorkRequestDetails()
{
return Json(new {});
}
If I have both of these in the code-behind file then I get this error: The current request for action 'SaveWorkRequestDetails' on controller type 'WorkRequestController' is ambiguous between the following action methods:
System.Web.Mvc.JsonResult SaveWorkRequestDetails() on type WorkRequest.Controllers.WorkRequestController
System.Web.Mvc.JsonResult SaveWorkRequestDetails(WorkRequest.ViewModel.WorkRequestViewModel) on type WorkRequest.Controllers.WorkRequestController
EXAMPLE 2
[HttpPost]
public JsonResult SaveWorkRequestDetails(WorkRequestViewModel viewModel)
{
// TODO: Save logic goes here
return Json(new { });
}
I need to pass the viewModel in order to save the user's selections. I am missing something and I am not sure what.
RegisterUIEventHandlers: function () {
$('#Save').click(function (e) {
// Check whether the form is valid. Note: Remove this check, if you are not using HTML5
if (document.forms[0].checkValidity()) {
e.preventDefault();
$.ajax({
type: "POST",
url: WorkRequest.SaveUrl,
data: ko.toJSON(WorkRequest.ViewModel),
contentType: 'application/json',
async: true,
beforeSend: function () {
// Display loading image
alert(ko.toJSON(WorkRequest.ViewModel));
},
success: function (result) {
// Handle the response here.
},
complete: function () {
// Hide loading image.
},
error: function (jqXHR, textStatus, errorThrown) {
// Handle error.
}
});
}
});
}
In the alert you see in beforeSend, in the AJAX POST within the javascript above, I see the selections the user makes. Everything works so I just want to pass this to the Controller's SaveWorkRequestDetails, how can I do this please. I was my understanding that the data parameter passed this on to the method specified in the url parameter.
The error message is clear. You have two action methods with the same name. So, call to the SaveWorkRequestDetails is ambigious as the error indicates.
You can overload functions in C# but it is not possible in ASP.NET MVC Framework.
It is not possible to have two SaveWorkRequestDetails() actions with different method signatures on the same controller in ASP.NET MVC.
Just remove the first SaveWorkRequestDetails(), and you will be fine.
I changed the dataType to json instead of application/json. This resolved the issue of the error stating there was not a parameterless default constructor. Now SaveWorkRequestDetails is being called.
RegisterUIEventHandlers: function () {
$('#Save').click(function (e) {
// Check whether the form is valid. Note: Remove this check, if you are not using HTML5
if (document.forms[0].checkValidity()) {
e.preventDefault();
$.ajax({
type: "POST",
url: WorkRequest.SaveUrl,
data: ko.toJSON(WorkRequest.ViewModel),
dataType: 'json',
async: true,
beforeSend: function () {
// Display loading image
alert(ko.toJSON(WorkRequest.ViewModel));
},
success: function (result) {
// Handle the response here.
},
complete: function () {
// Hide loading image.
},
error: function (jqXHR, textStatus, errorThrown) {
// Handle error.
}
});
}
});

How to fetch a specific div id from an html file through ajax

I have two html files called index.html & video.html
video.html holds coding like:
<div id="video">
<iframe src="http://www.youtube.com/embed/tJFUqjsBGU4?html5=1" width=500 height=500></iframe>
</div>
I want the above mentioned code to be crawled from video.html page from index.html
I can't use any back-end coding like php or .net
Is there any way to do using Ajax?
Try this...
$.ajax({
url: 'video.html',
success: function(data) {
mitem=$(data).filter('#video');
$(selector).html(mitem); //then put the video element into an html selector that is on your page.
}
});
For sure,send an ajax call.
$.ajax({
url: 'video.html',
success: function(data) {
data=$(data).find('div#video');
//do something
}
});
Yep, this is a perfect use case for ajax. When you make the $.ajax() request to your video.html page, you can then treat the response similar to the way you'd treat the existing DOM.
For example, you'd start the request by specifying the URI in the the following way:
$.ajax({
url: 'video.html'
})
You want to make sure that request succeeds. Luckily jQuery will handle this for you with the .done callback:
$.ajax({
url: "video.html",
}).done(function ( data ) {});
Now it's just a matter of using your data object in a way similar to the way you'd use any other jQuery object. I'd recommend the .find() method.
$.ajax({
url: "video.html",
}).done(function ( data ) {
$(data).find('#video'));
}
});
Since you mentioned crawl, I assume there is the possibility of multiple pages. The following loads pages from an array of urls, and stores the successful loads into results. It decrements remainingUrls (which could be useful for updating a progressbar) on each load (complete is called after success or error), and can call a method after all pages have been processed (!remainingUrls).
If this is overkill, just use the $.ajax part and replace myUrls[i] with video.html. I sepecify the type only because I ran into a case where another script changed the default type of ajax to POST. If you're loading dynamic pages like php or aspx, then the cache property might also be helpful if you're going to call this multiple times per session.
var myUrls = ['video1.html', 'video2.html', 'fail.html'],
results = [],
remainingUrls;
$(document).ready(function () {
remainingUrls = myUrls.length;
for (var i = 0, il = myUrls.length; i < il; i++) {
$.ajax({
url: myUrls[i],
type: 'get', // somebody might override ajax defaults
cache: 'false', // only if you're getting dynamic pages
success: function (data) {
console.log('success');
results.push(data);
},
error: function () {
console.log('fail');
},
complete: function() {
remainingUrls--;
if (!remainingUrls) {
// handle completed crawl
console.log('done');
}
}
});
}
});
not tested, but should be something similair to this: https://stackoverflow.com/a/3535356/1059828
var xhr= new XMLHttpRequest();
xhr.open('GET', 'index.html', true);
xhr.onreadystatechange= function() {
if (this.readyState!==4) return;
if (this.status!==200) return; // or whatever error handling you want
document.getElementsByTagName('html').innerHTML= this.responseText;
};
xhr.send();

jQuery call stack?

I have many instances of the same type of problem using jQuery. Probably because I am missing some basic knowledge (jQuery newb). In my $.Ajax calls to get data - on the success: I perform many calls to other functions based on the data that gets returned. The calls need to be made in a specific order but this does not seem to happen. If I have a call to another jQuery function that I wrote and then three line later have a call to yet another function (which depends on some events that happen in the first function call) the second call is happening first. Ran this with debugger set many times in two different $.Ajax calls and it happens this way. Am I doing something completely wrong?
BTW - the data is coming in just fine and populating my table and form items. Per request I am posting code below - the comments show that GetInventory needs to execute before BuidlNav
$(document).ready(function () {
$('#searchNow').css('visibility', 'hidden'); //Hide Search Now button
$("#popup").css("display", "none");
$('#submit').prop('disabled', true);
$.ajax({
type: "POST",
url: "mypage.aspx/mywebmethod",
contentType: "application/json; charset=utf-8",
data: "{}",
dataType: "json",
success: function (states) {
var jsonCodes = JSON.parse(states.d);
for (var i in jsonCodes) {
$("#Select0").append(new Option(jsonCodes[i].regionname, jsonCodes[i].region_id));
}
var first = getUrlVars()["region"];
if (first) {
debugger;
$.fn.SetAllSelectors(reg);
$.fn.GetInventory(1, 10, reg, 'rank', 'asc'); //This should happen first
$.fn.BuildNav(); // This depends on GetInventory having been executed already.
}
else {
var myText = 'United States';
$("#Select0 option").filter(function () {
return $(this).text() == myText;
}).first().prop("selected", true);
$.fn.GetChildRegions("Select0");
}
}
});
}
);
If GetInventory and BuildNav also use ajax, you'll need a structure more like this. When making ajax calls, the data is fetched while not holding up the next command line, so chances are your 2nd or 3rd function is being called before the first finishes.
$.ajax({
type: "POST",
url: "mypage.aspx/mywebmethod",
contentType: "application/json; charset=utf-8",
data: "{}",
dataType: "json",
success: function (states) {
getInventoryAndBuildNav(states);
},
...
});
function getInventoryAndBuildNav(states){
$.ajax({
....
url: "mypage.aspx/getinventory",
success: function (inventory) {
$.fn.BuildNav();
},
...
});
}
The best way to accomplish this is to build functions for each item and allow a callback method to be passed.
Think of it this way
$.ajax({
type: "POST",
url: "mypage.aspx/mywebmethod",
contentType: "application/json; charset=utf-8",
data: "{}",
dataType: "json",
success: function (states) {
//This will trigger second since we had to wait for the process to finish
alert('The Ajax call has been made, finished, and the data received');
}
});
//This will trigger FIRST since the ajax call was initiated, but we're still waiting
alert('The Ajax call has been made. We're moving on to the next call.');