I'm having an issue where jQuery.ajax() is calling my data objects functions. For example, I have an object structure similar to the following:
var TestFactory = (function () {
var _id;
var _attributes;
return {
createObject: function (objectId) {
var value = null;
_id = objectId;
_attributes = {};
function _showErrorStatus() {
$('label')
.css('background-color', 'red')
.css('color', 'black')
.text('jQuery called me...');
}
function _attr(key, value) {
if (value == null) {
return _attributes[key];
}
_attributes[key] = value;
return this;
}
return {
id: _id,
attributes: _attributes,
showErrorStatus: _showErrorStatus,
attr: _attr,
}
}
}
})();
I'd like to use this object as the data value for my jQuery.ajax() call, as follows:
var myObject = TestFactory.createObject(12345);
myObject.attr('name', 'Fred Flinstone');
$.ajax({
url: '/echo/json/',
type: 'GET',
data: myObject,
dataType: 'json',
});
The issue I'm running into is jQuery.ajax() is calling the showErrorStatus() function from the object returned by the factory --nowhere in my code do I call this function.
I like the OOP qualities I get out of using this object, so is there any way to handle this case without a significant rewrite (e.g., dropping all my functionality from the "class")?
NOTE: I found it difficult to explain this problem, so here is a complete running example on jsfiddle.
Use JSON.stringify (not a jQuery method).
$.ajax({
url: '/echo/json/',
type: 'GET',
data: JSON.stringify(myObject),
dataType: 'json',
});
http://jsfiddle.net/HJ9AS/10/
It happens because it's a feature, though not documented as far as I can tell.
If you pass an object, then it assumes you want it to call any functions that are values of object properties.
One way of doing it is to use a function like Underscore's pick(). It can be used to cherry-pick certain properties you need from the object. It is a useful library anyways, but you can also implement this simple method if you wish.
$.ajax({
url: '/echo/json/',
type: 'GET',
/* only send id and attributes! */
data: _.pick(myObject, 'id', 'attributes'),
dataType: 'json',
});
It might be a nice habit to always whitelist stuff, not just send everything blindly. Specifying exactly what to send can save you from future surprises (like the one you just encountered). Most of the time you simply don't want to send everything that is stored in your object.
You can also implement some way for your object to be able to return its sendable contens. It could get a .getJSON() method that just collects from the object everything to be sent.
Concerning the function calling:
Processing the data property uses $.param(), which has this in the docs:
As of jQuery 1.3, the return value of a function is used instead of the function as a String.
This is a feature, not a bug :). I understand the logic behind it, because if there is a function in the object that you just specified as data to be sent, there must be a good reason behind it...
Instead of passing data: myObject,
try setting this: var serializedObject = myObject.param()
then passing data: serializedObject
Check out jQuery's param function here.
Related
Tried looking in stackoverflow because this looked so trivial. Found many similar questions and read through them. Found no solution using these examples. Here is my code, can anyone help?
function testAjax() {
return $.ajax({
type: "GET",
url: '#Url.Action("Nodes","Competence", new { userId = Sven });',
contentType: "application/json;charset=utf-8",
dataType: "json"
});
}
var promise = testAjax();
promise.success(function (data) {
var dataConverted = JSON.stringify(data);
$('#tree').treeview({ data: dataConverted, multiSelect: true });
});
ASP.NET MVC method
public JsonResult Nodes(string userId)
{
var temp = userId;
var list = new List<Node>();
list.Add(new Node("Test1"));
list.Add(new Node("Test2"));
list.Add(new Node("Test3"));
return Json(list, JsonRequestBehavior.AllowGet);
}
EDIT:
Just before I was about to turn crazy on Halloween night, i figured out to try in a new session. Turns out it was just a caching problem..Thanks for the help everyone
Since your server may not expecting a request with JSON content, try removing the contentType parameter on your ajax call. Its default value is "application/x-www-form-urlencoded; charset=UTF-8" and is fine for most cases.
It's type should be "POST"
return $.ajax({
type: "POST",
url: '#Url.Action("Nodes","Competence")',
data: { userId: "Test" },
contentType: "application/json;charset=utf-8",
dataType: "json"
});
As it's a GET verb, it'll be easiest to pass this in as a querystring value. This also conforms better with a RESTful design.
For example replace #Url.Action("Nodes","Competence")
with
#Url.Action("Nodes","Competence", new { userId = id });
Then you can delete the data property. This will append ?userId=valueOfId into your url and then it should be mapped correctly to your action with the userId correctly populated.
Update
As #freedomn-m stated:
This will generate the url when the view is built server-side. If the
parameters never change, then fine - but it's relatively unlikely that
the parameters won't change, in which case you should add the url
parameters at runtime if you want them on querystring.
This is completely accurate. Without knowing your exact implementation I can only make assumptions. But technically you could wrap your ajax call in a function and then you could either pass in the userId and generate the url within that function or pass in the url, performing the url generation outside of the function.
This would mean that you only need one function that performs the ajax request and you can have another function that gets the userId (and possibly generates the url) and then passes that into the ajax function. How you store the userId is entirely up to you, but one thing I would suggest is investigating data attributes which is a fairly well defined way for storing data on html elements.
I am wondering is these is any way to access the results of a jquery ajax call in the form a traditional var set to function fashion. For example consider:
function getPoints(){
//An array of JSON objects
var Points;
$.ajax({
url: "js/retrievePointsDataJson.php",
dataType:'json',
type: 'POST',
}).done(function(data){
//console.log(data);
Points.append(data);
});
console.log(Points);
return Points;
}
The commented out console.log show the array of json objects whereas the outer one does not. Now, i have tries this:
var Points = $.ajax({ ...});
And i see the response text within a larger object, but am unsure how to access the responseText. console.log(Points.responseText) yields an undefined variable.
Is this possible with this approach? Here is another question that received a check mark with a similar issue.
I have another solutions, which is the encapsulate my code within the done() function and i will have access to all my data. I was just curious if what i am attempting to do is even doable.
Thank you.
yes it is possible, however, you must wait for the request to be complete before doing so. However, since you can't effectively force the return to wait until the data exists, you're only options are to return a deferred object instead, or re-write the function in such a way that allows it to accept a callback.
function getPoints(){
return $.ajax({
url: "js/retrievePointsDataJson.php",
dataType:'json',
type: 'POST'
});
}
getPoints().done(function(data){
console.log(data);
});
or
function getPoints(callback){
return $.ajax({
url: "js/retrievePointsDataJson.php",
dataType:'json',
type: 'POST',
success: callback
});
}
getPoints(function(data){
console.log(data);
});
Because the Ajax call is done asynchronously you shouldn't return it from the outside function. This would require that you somehow block until the asynchronous call completes. Instead you could pass in a callback function to the getPoints function that will handle the logic of using the points.
function getPoints(callback){
$.ajax({
url: "js/retrievePointsDataJson.php",
dataType:'json',
type: 'POST',
}).done(function(data){
callback(data);
});
}
The asynchronous nature of ajax can make things harder if your used to imperative programming, but it will make your user interface much more responsive.
The log you're calling in the outer function is working with an undefined variable because the function is asynchronous. You can't return it from getPoints because it won't have finished. Any work with the Points variable needs to happen inside the callback (the function passed to done).
In my function I am calling method passing $obj as a parameter in the function. I have defined currsel object, now in the method its showing me $obj.currsel.html() is not a function. I am sharing my code below.
$(document).on('change','.ui-modulelist1',function(e){
var $targetSel =coreFrameWork.frModuleContId;
var $thisVal= $(this).find("option:selected").val();
var loadUrl = '../ux_framework_New/_'+$thisVal+'/index.html';
commonFramework.initLoad({'url':loadUrl, 'currSel':$targetSel, 'mode':'autoload'});
});
var commonFramework ={
initLoad:function($obj){
$.ajax({
type: "GET",
url: $obj.url,
dataType: "html",
cache:false,
async:false,
beforeSend: function(xhr){
xhr.withCredentials = false;
},
success: function(html) {
$obj.currSel.html(html);
$obj.currSel.attr(projCommonAttr.autoloadAttr,'loaded');
commonFramework.contentSpecific({'currSel':$obj.currSel,'mode':$obj.mode});
},
error: function(qXHR, textStatus, errorThrown){
}
});
},
It's hard to tell without seeing an example url. What is coreFrameWork.frModuleContId? Try logging it in your console. I'm guessing you need to do
var $targetSel = $(coreFrameWork.frModuleContId);
Is this:
var $targetSel =coreFrameWork.frModuleContId;
a jQuery object?
The function html() belongs to jQuery, so if your object is not a jQuery one, it won't find that method.
I don't exactly know what that variable is, but you can try by wrapping it into a jQuery object:
var $targetSel = jQuery(coreFrameWork.frModuleContId);
Also, it is not a good practice to use names beginning with $ to name simple js objects (those names are often used to name variables representing jQuery objects or so).
Hope this helps you.
Regards,
Marcelo
url: $obj.url,
This parameter needs to be a string. If you want a dynamic url from your obj variable do this:
url: $obj+".php", // .php or whatever the file type is of the page you're requesting
If I have an array like
price=["1#1000", "1000#2000"]
how to convert it into JSON so that it can be send into ajax call of jQuery
$.ajax({
type: 'POST',
url: '',
data: {
'price': price
},
dataType: 'JSON',
success: function(data) {
console.log("success");
console.log(data);
var products = data.products;
console.log(products);
},
});
Since you already posted...parts of jQuery, here is a jQuery plugin that should do it
http://plugins.jquery.com/plugin-tags/stringify
|EDIT| The jQuery-plugins-site is put down for a while.
Anyways, you a looking for a function called Stringify. You can read more about it here:
http://www.json.org/js.html
A simple google-search should give you plenty results.
When writing price=["1#1000", "1000#2000"] you already have your data represented as a javascript array.
It should be possible for you to simply pass this as an argument as you have described within your use of the $.ajax method.
Alternatively (if you really need to parse price as a json object) see the jQuery builtin function for this: http://api.jquery.com/jQuery.parseJSON/
But recheck that this is not just possible, as you have described it, if not, what errors are you getting?
I have this code snippet in .js file
$(function () {
// KeyDates
var url = "http://localhost:8732/Design_Time_Addresses/Intel.IIP.MDF.WCF/ProgramCalendarService/GetKeyDatesCalendarNew";
$.ajax({
url: url,
data: null,
type: 'POST',
contentType: 'application/json',
dataType: 'json',
success: function (GetKeyDatesCalendarDataNew) {
alert(GetKeyDatesCalendarDataNew);
$(document).ajaxStop($.unblockUI);
}
});
});
How do i process the key value pair in GetKeyDatesCalendarDataNew?
You probably want to know how to access an object's props. For that, use the for in loop to iterate over the object's values:
success: function (GetKeyDatesCalendarDataNew) {
for(var key in GetKeyDatesCalendarDataNew)
{
var value = GetKeyDatesCalendarDataNew[key];
// do somehitng based on the key and/or value iterated
}
}
For this case, the argument of the success function is the evaluated JSON that was returned from the Ajax request. Therefore GetKeyDatesCalendarDataNew, which you should rename to something like data, becomes the actual data that your server returned.
You can only process the data if you know its structure. One simple way of knowing this would be to do console.log(GetKeyDatesCalendarDataNew) and then easily process it with a for loop if it's an array or for x in.. if it's an object.
You can use JQuery "getJSON" function where you need to pass the url and specify a callback function.Your ajax call will be handled by the getJSON function. In the callback function, you can access the Keys as properties. A nice example
Lav G
$.each(GetKeyDatesCalendarDataNew,function(key,value){
//do something here
})