Function result array inside $.ajax is converted to string - javascript

I need to pass array of ids with $.ajax data variable. The array is a result of a function. If i declare this function outside $.ajax it sends array correctly. But if i put same function code inside $.ajax (which is preffered for me), i get it as a string.
function mySort(){ // Do not pass hidden clones
var items = [];
$('#fp_parameters_list').children().each(function(){
if ($(this).is(':visible')) {
items.push($(this).attr('data-parameter-id'));
}
});
return items;
}
// This gives correct ordering
$.ajax({
url: '/echo/json/',
type: 'post',
dataType: 'json',
data: {
ordering: mySort()
}
});
// This gives ordering as a string
$.ajax({
url: '/echo/json/',
type: 'post',
dataType: 'json',
data: {
ordering: function(){ // Do not pass hidden clones
var items = [];
$('#fp_parameters_list').children().each(function(){
if ($(this).is(':visible')) {
items.push($(this).attr('data-parameter-id'));
}
});
return items;
}
}
});
Here's fiddle: http://jsfiddle.net/vxLrN/7/
You can see that first request is sent with ordering as an array, while second pass ordering as string, although, functions are absolutely equal.
How can i put function inline and still get array result?
Thanks

Well make sure that you invoke this anonymous function in order to assign the proper result (array of strings) to the ordering parameter:
data: {
ordering: (function () { // Do not pass hidden clones
var items = [];
$('#fp_parameters_list').children().each(function() {
if ($(this).is(':visible')) {
items.push($(this).attr('data-parameter-id'));
}
});
return items;
})(); // <!-- Here call the anonymous function to get its result
}

Just use $.map to build the array directly instead
$.ajax({
url: '/echo/json/',
type: 'post',
dataType: 'json',
data: {
ordering: $.map($('#fp_parameters_list').children(':visible'), function(el) {
return $(el).data('parameter-id');
})
}
});

Related

AutoComplete inside keyup jquery weird behaviour

I've a conditional ajax function call. On receiving response, data is binded to the autocomplete. The problem is that, on entering first key, Autocomplete list doesn't shows up even though it has values binded to it. The list shows up only after entering the subsequent letter(s).
$("#AutoComplete").on('keyup', function (event)
{
if ($("#AutoComplete").val().length <= 5 )
{
GetData();
}
});
function GetData()
{
$.ajax({
type: "POST",
url: "../Controller/function",
contentType: "application/json; charset=utf-8",
data: '{"key":"' + $("#AutoComplete").val() + '"}',
dataType: "json",
success: function (data)
{
var output= $.map(data, function (item)
{
return {
label: item.Name,
value: item.ID
};
});
$("#AutoComplete").autocomplete({
source: output,
autoFocus: true,
});
}
});
}
Consider the following example.
$("#AutoComplete").autocomplete({
source: function(req, resp) {
if (req.term.length <= 5) {
$.ajax({
type: "POST",
url: "../Controller/function",
contentType: "application/json; charset=utf-8",
data: {
key: req.term
},
dataType: "json",
success: function(data) {
var output = $.map(data, function(item) {
return {
label: item.Name,
value: item.ID
};
});
resp(output);
}
});
}
},
autoFocus: true,
});
You can use a Function for the Source:
Function: The third variation, a callback, provides the most flexibility and can be used to connect any data source to Autocomplete, including JSONP. The callback gets two arguments:
A request object, with a single term property, which refers to the value currently in the text input. For example, if the user enters "new yo" in a city field, the Autocomplete term will equal "new yo".
A response callback, which expects a single argument: the data to suggest to the user. This data should be filtered based on the provided term, and can be in any of the formats described above for simple local data. It's important when providing a custom source callback to handle errors during the request. You must always call the response callback even if you encounter an error. This ensures that the widget always has the correct state.
https://api.jqueryui.com/autocomplete/#option-source

Send form elements and array through $.ajax()

I need to pass through $.ajax() method some form elements and an array too. How can i send serialize and array by ajax?
my code bellow:
function loadgraficosajax(){
var arr = ['331234','142323','327767'];
var data = $('#p-form').serialize;
$.ajax({
type: "POST",
url: "/page/show",
data: data,
dataType : 'html',
success: function (msg) {
$(document).ajaxComplete(function (event, request, settings) {
$('.has-error').removeClass('has-error');
$(document).off('ajaxComplete').off('ajaxSend');
$('#addajax').html(msg);
});
}
});
}
serialize is a method in jQuery, not a property, so you should call it in this way:
var data = $('#p-form').serialize();
and to pass your array you need to use param method and modify your array to be inside Object, where array name is object property:
var arr = { arr: ['331234','142323','327767'] };
var data = $('#p-form').serialize();
data += '&' + $.param( arr );
param will transform your object to serialised string:
console.log($.param( arr )); // "arr[]=331234&arr[]=142323&arr[]=327767"
var formData = new FormData($('#p-form')[0]);
var arr = ['331234','142323','327767'];
// append array to formData
formData.append('arr',JSON.stringify(arr));
$.ajax({
type: "POST",
url: "/page/show",
data: formData,
success:.....
You could bundle the two items together in a stringified object which you can send:
function loadgraficosajax(){
var arr = ['331234','142323','327767'];
var data = $('#p-form').serialize();
var request = {
array: arr,
elements: data
}
var data = JSON.stringify(request);
$.ajax({
type: "POST",
url: "/page/show",
data: data,
dataType : 'json',
success: function (msg) {
$(document).ajaxComplete(function (event, request, settings) {
$('.has-error').removeClass('has-error');
$(document).off('ajaxComplete').off('ajaxSend');
$('#addajax').html(msg);
});
}
});
}

How to call a method of a javascript object inside ajax

Given this code,
var submit = {
send:function (form_id) {
var url = $(form_id).attr("action");
$.ajax({
type: "POST",
url: url,
data: $(form_id).serialize(),
dataType: 'json',
success: function(result) {
this.ret(result.message);
},
error: function(result) {
// Some error message
}
});
},
ret:function (result) {
this.result_data = result;
},
result_data:""
};
will send a data from the form to a controller which if will return a json
$result['message'] = validation_errors();
echo json_encode($result);
I try to call this javascript object in this code,
var res = submit.send(form_id);
wherein form_id is the form id, and look for the output using
console.log(res);
In the console, it shows undefined. After searching for an explaination using google and stackoverflow itself I got the idea that,
this.ret(result.message);
is being called inside ajax which is another object, indicating that it's not part of it's method.
My problem is, how to call the method ret() inside ajax?
Is anyone can explain it to me?
There is several ways to deal with it.
One is ES5 compatible (and this is actually quite common pattern):
var submit = {
send: function (form_id) {
var url = $(form_id).attr("action");
var self = this; // << this is binded to self varialble
$.ajax({
type: "POST",
url: url,
data: $(form_id).serialize(),
dataType: 'json',
success: function(result) {
self.ret(result.message); // << replaced this to self so it has all the methods from the submit object.
},
error: function(result) {
// Some error message
}
});
},
ret:function (result) {
this.result_data = result;
},
result_data:""
};
And another is using arrow function from ES2015 plus deferred object returned by $.ajax:
var submit = {
send: function (form_id) {
var url = $(form_id).attr("action");
$.ajax({
type: "POST",
url: url,
data: $(form_id).serialize(),
dataType: 'json'
})
.then((result) => {
this.ret(result.message); // << arrow function is called in context of the parent function, so no needs to change anything.
})
.fail(function(result) {
// Some error message
});
},
ret:function (result) {
this.result_data = result;
},
result_data:""
};
Explanation: context of this in callback function will be bind to global scope not to the object's one. So you need somehow to change it.
You can actually match and mix these two methods.
You can also use bind or put success as a object method. As it mentioned in other answers. Same thing, you want to keep this to be object's context.
There is a good article about this in javascript.
You've two options.
1. The "bind()" method (recommended)
The method bind is for changing the context of a function. From the docs:
The bind() method creates a new function that, when called, has its
this keyword set to the provided value, with a given sequence of
arguments preceding any provided when the new function is called.
Here the bind will change the context of success function with the reference of this i.e. the submit.
$.ajax({
type: "POST",
url: url,
data: $(form_id).serialize(),
dataType: 'json',
success: function(result) {
this.ret(result.message);
}.bind(this), // <== bind method
error: function(result) {
// Some error message
}
});
That .bind(this) can also be written as .bind(submit);
2. Using the scope variable
Since you already have access to the submit variable, why not directly call with submit instead of this
$.ajax({
type: "POST",
url: url,
data: $(form_id).serialize(),
dataType: 'json',
success: function(result) {
submit.ret(result.message);
}.bind(this),
error: function(result) {
// Some error message
}
});
success: function(result) {
this.ret(result.message);
}
In the above block the this refers to the function you are operating in.
To use ret method you should use it submit.ret.
I have a small code fragment, that simulates this:
var submit = {
send:function (form_id) {
var self = this;
setTimeout(function()
{
console.log('send', this);
self.ret('message'); //will do
//submit.ret('message'); //will do
//this.ret('message'); this.ret is not a function
//ret('message'); ret is not defined
}, 0);
},
ret:function (result) {
console.log('ret', result, this)
this.result_data = result;
},
result_data:""
};
There you can see your possible choices to handle this.
Or use this fiddle: https://jsfiddle.net/syqjwk2q/#&togetherjs=mpwEnNDeIJ
In the submit define
self = this
And then use ret() with self: self.ret()

Javascript Variable Showing undefined

I have a global javascript array and i am able to call values from it at the beginning of the function but after that, when i alert leaders[i], it shows as undefined:
It appears the problem occurs when there are two ajax calls nested in each other, JS cannot seem to find the values in the array.
JS
function getLeaders(bool) {
var leaders = new Array();
leaders.push('444');
leaders.push('111');
$.ajax({
url: 'url',
crossDomain: true,
type: 'post',
data: {
'clubID': curClub
},
success: function (data) {
for (var i = 0; i < leaders.length; i++)
{
alert(leaders[i]); <===== working fine here
$.ajax({
url: 'someurl',
crossDomain: true,
type: 'post',
data: {
'id': leaders[i] <====== works here
},
success: function(data3) {
alert(leaders[i]); <======= undefined here
var json3 = jQuery.parseJSON(data3);
}
});
}
}
});
};
Since the call is asynchronous the value of i is more than likely leader.length by the time the call returns. So you are probably accessing an index that is out-of bounds.

Can't query JSON using jQuery

I'm using jQuery to grab some JSON data. I've stored it in a variable called "ajaxResponse". I cant pull data points out of it; I'm getting ajaxResponse.blah is not defined. typeof is a string. Thought it should be an object.
var getData = function (url) {
var ajaxResponse = "";
$.ajax({
url: url,
type: "post",
async: false,
success: function (data) {
ajaxResponse = data;
}
});
return ajaxResponse;
},
...
typeof ajaxResponse; // string
ajaxResponse.blah[0].name // ajaxResponse.blah is not defined
make sure you specify option dataType = json
$.ajax({
url: url,
type: "post",
dataType: "json",
async: false,
success: function (data) {
ajaxResponse = data;
}
});
Q8-coder has the right of it, but to give you some details: your server is really passing back a string that you've formatted into JSON. You'll need to tell jQuery what to expect, otherwise it just assumes it received a string.
Add the following to your $.ajax options:
dataType: "json"
Also, refer to the jQuery API for examples and documentation for these options.

Categories