issue while looping a json array - javascript

I retrieve some option for a select from an ajax call in json format.
The code I have set up to display the new options in the select (replacing the existing ones) is the following:
success: function (data){
var $select = $('#dettaglio');
$select.html('');
$.each(data, function(key, val){
$select.append('<option id="' + val.id + '">' + val.text +'</option>');
})
}
while the json is like this:
[
{"id":"1","text":"J-Invest Spa"},
{"id":"2","text":"J-A Holding S.r.l."},
{"id":"3","text":"J-Invest Advisory & Servicing S.r.l."},
{"id":"4","text":"J-Invest Immobiliare e Consulenza S.r.l."}
]
Running this code leads to an error that is not easy to understand:
TypeError: invalid 'in' operand e
...===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in
e)}r=b(o);var _={}...
jQuery is throwing an error but this is not helpful to see where my code is wrong. Any hint?

Yes I get an array from mysql and encode it with json_encode. The data received from the server will always be of string type. You need to parse it to convert to JSON format. Can you try this?
success: function(data) {
data = JSON.parse(data);
Or in case, if you are using some Old IE, you can also try:
success: function(data) {
data = $.parseJSON(data);

The easiest way would be to change a bit on your PHP, by adding this:
header('Content-type: application/json');
Just that. jQuery is automatically set to detect the encoding of the returned data. If later you decide to send something else, you just change the header.
Warning: This function must be one of the first ones to be executed, before ANY output. Otherwise, it will throw errors at you.

Related

js - Ordered JSON data from an ajax endpoint is in wrong order, and caching is not the problem

I have an application using jquery 2.0.3 and a CakePHP 2.x back-end. It's a legacy application, which is why we're using those versions.
Part of the application features a <select id="orderTags"> which when changed fires an ajax request to an endpoint /get_tags. This returns a JSON-encoded response which is then used to update some list items in an element called #tags.
The code to make the request works by listening for changes to #orderTags:
$('#orderTags').change(function() {
var order = $('#orderTags option:selected').val();
$("#tags ul").html('');
get_tags(order);
});
This then executes get_tags() and passes in a string for ordering, which are set as follows:
Order by date added (name: "date")
Order by name ASC (name: "name_asc")
Order by name DESC (name: "name_desc")
I can see in my browser Network tab that requests are being made to the appropriate endpoint - giving a 200 status - and passing in the appropriate string as a $_GET parameter:
/get_tags?orderby=date
/get_tags?orderby=name_asc
/get_tags?orderby=name_desc
When viewing the Response in my Network tab, the endpoint is producing the correct (i.e. different order in each case) JSON. For example the screenshots below so the response from (2) and (3) above, and as you can see the order is alphabetical:
I'm using the $.each function in jquery to loop through the response. The following is the code inside get_tags() referenced above:
function get_tags(order) {
order = order || "date";
$.ajax({
url: '/get_tags',
dataType: 'json',
data: {'orderby': order},
cache: false
}).done(function (data) {
console.log(data);
var items = '';
$.each(data, function (key, val) {
items += '<li id="tag-' + key + '"><i class="fa-li fa fa-tags"></i>' + val + '</li>';
});
$("#tags ul").append(items);
});
The console.log(data) is giving a different output to the response from the script. I've used cache: false and can see jquery is appending the _ parameter in the URL.
So for example I've posted the console.log output from the above 2 screenshots. The same data - in totally the wrong order - is being presented in each case:
Why is this happening?
In case anyone else has the same problem I've found the solution. The problem - as mentioned by #Pointy in the comments - was related to:
There is no set ordering of properties in JavaScript objects. If you want a fixed ordering, use an array
The data is being returned by the /get_tags endpoint using PHP's json_encode functionality.
The solution was to use JSON_FORCE_OBJECT where the output was being produced, i.e.
echo json_encode($output, JSON_FORCE_OBJECT);
Where $output is an array of data that the endpoint should return.
There is more information about why this works here: How do I `json_encode()` keys from PHP array?. It means that the data returned has array keys which are important for preserving the order.
Screenshot Example of the JSON returned for ordering A-Z. Note the array keys highlighted green versus the original screenshots (which lack array keys):
The $.each code needed tweaking slightly as well. This is because key now represents the array key (highlighted in green on the screenshot above) and val is the object of data returned by the endpoint which can be accessed with dot-notation:
$.each(data, function (key, val) {
items += '<li id="tag-' + val.id + '"><i class="fa-li fa fa-tags"></i>' + val.name + '</li>';
});

JSON Parse Error: unexpected end of data at line 1 column 1 of the JSON data

I have a database, analysis.php and index.php webpages. The analysis.php gets the data from the database, sorts it in a required pattern, and then echoes the json_encode($array); into a div with the id 'data'. I am trying to get that JSON Data and parse it in the index.php page.
However I am getting an error. SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data
I am trying to get this data everytime the user selects an option from a select box.
My jQuery code is:
$(document.body).on('change', '.select' , function () {
var identification = $(this).val();
var JSONText = $(this).closest('div[id|="module"]').find('p[id="JSON"]');
JSONText.load('analysis.php?data=' + identification + ' #data');
console.log("JSON Imported: '" + identification + "'");
var obj = jQuery.parseJSON(JSONText.text());
console.log(JSONText.text());
});
EDIT: As you can see I have the snippet console.log(JSON.text());. The output of the JSON that I get is correct. The only issue I think might be is that the quotes are all " instead of the JSON quotes being different from the outer quotes.
jQuery.load is asynchronous, you're trying to parse the JSON before its actually loaded. Using jQuery.getJSON loads the content, does the parsing and provides a callback you can bind to.
jQuery.load loads the content as HTML and sets the innerHTML of the selected element, you could bind the complete handler here aswell, but you may encounter issues by loading the content as HTML and then using text to retrieve it from the DOM as some parts of your JSON may be interpreted as HTML elements.
Better use this:
$(document.body).on('change', '.select' , function () {
var identification = $(this).val();
$.getJSON(
'analysis.php?data=' + identification + ' #data',
function (data) {
console.log(data);
}
);
});
In addition to LJ_1102's solution, here is a way to fix your current snippet:
JSONText.load('analysis.php?data=' + identification + ' #data', function() {
console.log("JSON Imported: '" + identification + "'");
var obj = jQuery.parseJSON(JSONText.text());
console.log(JSONText.text());
});

Transforming a json format variable into a javascript array

I am using the Django framework to build a website.
In the Python file (views.py) I send to the Javascript function an array that has been transformed to json data
Python:
json_data=[1,2,3]
return HttpResponse(json.dumps(json_data), mimetype='application/json')
Then, in Javascript I display the json data in the html.
JavaScript:
function get_variable(){
$.get("/xhr_test/json/", function(json_data) {
$('.square').append('<p> ' + json_data + ' </p>');});
};
So far everything works. However, I would like to convert the "json_data", which I believe is a string, into an array.
I tried doing this:
function get_variable(){
$.get("/xhr_test/json/", function(json_data) {
var array = json_data.split(',');
$('.square').append('<p> ' + array[0]+ ' </p>');});
};
Unfortunately, this doesn't work.
Can someone please explain to me what could I do to convert the "json_data" variable into an array in JavaScript?
Thanks a lot.
When you send around data in JSON format it is a string (the main data), but a string formated in such a way that it's easy to recover the data with the original types (ie, your array). Javascript and jquery have different ways to do that. Using jQuery,getJSON is probably the most direct:
http://api.jquery.com/jQuery.getJSON/
You can use your browsers javascript console to see what exactly do your JS variables look like.
"this doesn't work" it's too vague...
Anyway, if I understood your problem, you are dealing with a string, not a JavaScript array... you have to evaluate the data returned from the ajax call:
var theJavaScriptArray = eval('(' + json_data + ')');
or better... use jQuery.ajax and specify json as dataType: jquery doc
In the end, thanks to Zah I discovered the "javascript console", which I didn't know it existed.
I could see that the error was that the "json_data" variable was not a string.
So this is the solution that worked for me:
function get_variable(){
$.get("/xhr_test/json/", function(json_data) {
var b=json_data.toString().split(',');
$('.square').append('<p> ' + b[0] + ' </p>');
});
};
There is a shorthand in jQuery to parse the json string automatically: jQuery.getJSON()
$.getJSON('/xhr_test/json/', function(data) {
console.log(data); // Here data is already a JavaScript object
});
This is basically the same as:
$.ajax({
url: "/xhr_test/json/",
dataType: "json",
success: function(data) {
console.log(data); // Here data is already a JavaScript object
}
});
Which again is about the same as:
$.ajax({
url: "/xhr_test/json/",
success: function(data) {
var json = $.parseJSON(data); // Here data is a string
console.log(data); // And json is JavaScript object
}
});

How to get JSON from PHP to JS?

I have really been searching for almost 2 hours and have yet to find a good example on how to pass JSON data from PHP to JS. I have a JSON encoding script in PHP that echoes out a JSON script that looks more or less like this (pseudocode).
{
"1": [
{"id":"2","type":"1","description":"Foo","options:[
{"opt_id":"1","opt_desc":"Bar"},
{"opt_id":"2","opt_desc":"Lorem"}],
{"id":"3","type":"3","description":"Ipsum","options:[
...
"6":
{"id":"14","type":"1","description":"Test","options:[
...
etc
Problem is, how can I get this data with JavaScript? My goal is to make a .js script that generates a poll based on these JSON datas, but I honest to god can't find any examples on how to do this. Guessing it is some something like:
Obj jsonData = new Object();
jsonData = $.getJson('url',data,function()){
enter code here
}
Any links to any good examples or similar would be highly appreciated. And I thought that encoding the data in PHP was the tricky part...
EDIT:
I got this code snippet to work, so I can review my whole JSON data in JS. But now I can't seem to figure out how to get to the inner data. It does print out the stage number (1-6) but I can't figure out how to get the question data, and then again the options data within each question. Do I have to experiment with nested each loops?
$(document).ready(function()
{
$('#show-results').click(function()
{
$.post('JSAAN.php', function(data)
{
var pushedData = jQuery.parseJSON(data);
$.each(pushedData, function(i, serverData)
{
alert(i);
})
})
})
});
The idea here is to get into the question information in the middle level and print out the qusetion description, then based on the question type - loop through the options (if any) to create checkbox/radiobutton-groups before going on to the next question. The first number represents which stage of the multi stage poll I am currently working on. My plan is to divide it into 6 stages by hiding/showing various divs until the last page where the form is submitted through Ajax.
Not sure but I think, you can use
$.getJSON('url', data, function(jsonData) {
// operate on return data (jsonData)
});
now you can access and operate on the PHP json data,
if you're going to use it outside the getJson call you can assign it to a variable
var neededData;
$.getJSON('url', data, function(jsonData) {
neededData = jsonData;
});
Try the jQuery documentation: http://api.jquery.com/jQuery.getJSON/
This example should get you started:
$.getJSON('ajax/test.json', function(data) {
var items = [];
$.each(data, function(key, val) {
items.push('<li id="' + key + '">' + val + '</li>');
});
$('<ul/>', {
'class': 'my-new-list',
html: items.join('')
}).appendTo('body');
});
This example is based on the JSON structure being;
{
"one": "Singular sensation",
"two": "Beady little eyes",
"three": "Little birds pitch by my doorstep"
}
Do not use echo in PHP. It will print string not JSON.
Use json_encode to pass JSON to javascript.
Use can use each to get the values in JSON at javascript end.
Example
http://www.darian-brown.com/pass-a-php-array-to-javascript-as-json-using-ajax-and-json_encode/
If you are using JQuery there is a really simple solution to your approach as you can see here: http://api.jquery.com/jQuery.getJSON/.
Otherwise I just want you to explain that there is no way to access your JSON directly in JavaScript as you tried in your code above. The main point is, that JavaScript runs on your browser while your PHP script runs on your server. So there must definitely be a communication between them. So you have to request the data from the server over http I would suggest.
HTH

how to access and output json results from $.ajax() success callback

I'm using coldfusion and jquery. This is my first real go at jquery and I've searched and read for a long time without cracking this so any help would be greatly appreciated...
Ok, I have an autocomplete returning an id. I'm then passing the id to a second function that returns an array of datatype json. The autocomplete works great and I can get the json to display in an alert box but am a bit stuck on how to use the json results.
I'm trying to loop through the json array and write the values into radio buttons, which then dynamically display on page... So the whole idea is this.
user is selected from drop box and id is returned
user id from selection is passed to user options function and user options are returned in json arrary.
json array is looped through and on each iteration a radio button is created with appropriate values.
all radio buttons are then output to screen for access and selection.
The code I have so far is this :
<script type="text/javascript">
// <!--
$(document).ready(function() {
$("#userName").autocomplete({
cache:false,
source: "/jqueryui/com/autocomplete.cfc?method=getUser&returnformat=json",
//setup hidden fields
select:function(event,ui) {
var uid = ui.item.id;
$("#userid").val(ui.item.id);
// start call to get user options
$.ajax({
type: "POST",
url: "/jqueryui/com/autocomplete.cfc?method=getUserOptions&returnformat=json",
data: ({ userid: uid }),
success: function(data) {
alert(data)
}
});
/// end call to get user options
}
});
});
// --->
</script>
The json displayed in the "alert(data)" popup, which looks fine, is this :
[{"productname":"licence free","quantity":1,"term":12,"id":1},
{"productname":"licence basic","quantity":1,"term":24,"id":1},
{"productname":"licence full","quantity":1,"term":12,"id":2}]
I need to know how to loop through this data and create a radio button for each option, probably something like this, and display them all on screen, which I'm guessing I'll just write to a via the dom once I have something to write :
<input type="radio" name="userOption" value="#id#|#qty#|#term#">#productname#
I have tried a few things, without success, such as :
for(var i =0;i<Data.length-1;i++)
{
var item = Data[i];
alert(item.productname + item.id);
}
And
$.each(data.items, function(i,item){
alert(item);
if ( i == 3 ) return false;
});
I couldn't get either of these to work.
Anyway this is getting a bit long winded. Hope it's clear, and again any help or suggestions appreciated.
Thanks!
First check the datatype of the data parameter returned. You might first need to use .parseJSON() to construct a JSON object.
Then your for loop syntax is not correct. this code works for me:
var data = [{"productname":"licence free","quantity":1,"term":12,"id":1},
{"productname":"licence basic","quantity":1,"term":24,"id":1},
{"productname":"licence full","quantity":1,"term":12,"id":2}];
for (var i=0; i<data.length; i++) {
alert(data[i].productname);
}
Here's a jsfiddle
Try checking parseJSON jquery function.
I quess that the type is a string? If so try it with the javascript function eval. It converts a string to a javascript type.. in your case something like this should work:
Var new_data = eval(data);
Now it should be a workable array/object
Edit: to stay with the data variable:
data = eval(data);
Edit 2:
Your ajax call misses the dataType property:
dataType: "json"
With this you dont need the stuff above i said
Use a each loop to get data and appendTo function to print data in an HTML element with result1 id:
dataType:"json", //nature of returned data
success: function(data) {
var content = '';
$.each(data, function(i, dbdata) {
content += '<p>' + dbdata.columnName + '<p>';
});
$(content).appendTo("#result1");
}

Categories