why does javascript reorder data I get from the server - javascript

I am using jquery ajax to get some data from server and I get them back in this format:
however when I print this data in javascript it gets printed ascending by id instead of descending like the data I recieved.
when I print it here it is how it looks:
it self orders everything in ascending order by letter and number, why does it do this?
Here is my code:
$.ajax("{{route("backend.blog.categories.getparents")}}", {
method: 'GET',
dataType:'json',
success: function(result) {
console.log("result.categories: " + result.categories);
I use this data to populate a select box and I need it to be in the same order I recieve it in and not ordered by javascript automatically. How do I do this?
$.each( result.categories, function( key, value ) {
console.log("key: " + key);
if(key != exclude){
parentCategories += '<option value=' + key + '>' + value + '</option>';
}
});
code on the server side:
$parentCategories = array();
foreach ($categories as $category) {
$parentCategories += [$category->id => $category->title];
}
if($categories){
return response()->json([
'status' => 'success',
'categories' => $parentCategories,

JSON - the notation you're using - doesn't have an order. If you want to give it a specific order you will have to save that explicitly or use an array. Either way, although according to the spec the order is not guaranteed, modern browsers in general do keep the order. Numeric looking keys however form a weird exception that you found now.
let orderKept = {"a2": "a", "a1": "b"};
let orderNotKept = {"2": "a", "1": "b"};
console.log(orderKept, orderNotKept);
Example way how this would typically be done properly (guaranteed to work by the spec and not just browser implementations) is an array of objects where every object has its own id property.
Of course you could move away from JSON, but keep the same notation and build your own parser, however I would definitely not recommend that.

Related

why does returning JsonResult from a Dictionary change the sort order?

I have the following controller action:
public JsonResult GetInvestors(int bank)
{
var investors = _context.Investors
.Where(i => i.BankNumber == bank)
.Select(i => new { InvestorId = i.InvestorId.ToString(), InvestorName = i.InvestorName + " (" + i.BankNumber + ")" })
.OrderBy(i => i.InvestorName)
.ToDictionary(i => i.InvestorId, i => i.InvestorName);
return Json(investors, JsonRequestBehavior.AllowGet);
}
And the following javascript to call that action that for now just starts the debugger so I can browse the result:
function getInvestors(bank)
{
$.ajax
({
url: "/InvestorDetail/GetInvestors",
type: "POST",
data: { bank: bank },
dataType: "json",
success: function (returnedData) { debugger; }
});
}
If I watch investors in the controller action, it is sorted by the investor name, which is what I want. However, when I get to the javascript debugger and watch returnedData, the data comes in sorted by the investor ID.
Alternately, if I put OrderBy after ToDictionary and order by Value, in the javascript debugger the json structure of the result is different but it is sorted by investor name like I want.
Why would the sort order change when returned from a Dictionary?
Thank you.
For purposes of enumeration, each item in the dictionary is treated as a KeyValuePair structure representing a value and its key. The order in which the items are returned is undefined.
See official msdn documentation
You can use sorted Dictionaries though, or sort it properly on the client side.
You can't sort a dictionary, although you can get a representation of a sorted dictionary!
You could try something like
import collections
Dictionary_Sorted = collections.OrderedDict(x)
x being an object with key valued pairs.
This is the same case for C# as well.
I like to change my Dictionary to a list by say.
var newList = thisDictionary.ToList();
newList.Sort((a,b) => a.Value.CompareTo(b.Value));
I like the one liner approach. It is simple and elegant.
If you would like to sort it descending then switch the values as such.
newList.Sort((a,b) => b.Value.CompareTo(a.Value));

Deconstructing a JSON object

A JSON encoded array is passed from PHP to an HTML document. It is not at all clear how to deconstruct that array into javascript-usable pieces. For example, consider the following HTML:
<div id="options">{"foo":[{"id":1},{"id":3}], "bar":[{"id":2},{"id":4}]}</div>
The only a priori known element of this array is that the key id exists. The indices, I know, can be found with
var data = JSON.parse($("#options").text());
$.each(data, function(index) {
// index will be foo & bar
});
The use case is to use the index and id to add an attribute to elements in a document. I have not yet stumbled upon the technique to return the ids associated with each index. How best can that be done?
Edit - a clarification of the use case - the long story
I want to re-enable some options on a form based on properties of an entity (in a Symfony application). Disabled options cannot be modified, but are also not not persisted - their values are set to null. I've built a service to determine the option elements that are disabled and send those elements to the form document as a JSON object. I'm assuming for now that the specific options are not known until the form is created. In the example above, foo & bar represent possible options, and the ids correspond to the option. For example, a Household entity might have Reason options selected but disabled of "Low wages" (id = 3). This would show up in as ...id="options">{"reasons":[{"id":3}]}<.... I would the use this information to remove the disabled="disabled" attribute from the set of checkboxes for the Reason, id=3 (i.e., id="household_reasons_3") field. I hope this makes sense.
Edit #2, by request - the PHP code creating the object.
The result of getMetatData() appears in the document at #options. From the above edit, the Household entity is $object.
public function getMetaData($object) {
$data = array();
$className = get_class($object);
$metaData = $this->em->getClassMetadata($className);
foreach ($metaData->associationMappings as $field => $mapping) {
if (8 === $mapping['type']) {
$data[$field] = $this->extractOptions($object, $field);
}
}
return json_encode($data);
}
private function extractOptions($object, $field) {
$data = [];
$method = 'get' . ucfirst($field);
$itemName = substr($field, 0, -1);
$getter = 'get' . ucfirst($itemName);
$entity = $object->$method();
foreach ($entity as $item) {
if (method_exists($item, 'getEnabled') && false === $item->getEnabled()) {
$data[] = ['id' => $item->getId()];
}
}
return $data;
}
Long before the infinite monkey limit was reached I stumbled on a method to create the results I was looking for. My thanks go out to all who pushed for clarifications. So, for the object
{"foo":[{"id":1},{"id":3}], "bar":[{"id":2},{"id":4}]}
the script
var data = JSON.parse($("#options").text());
var i = 0
var output = [];
$.each(data, function(index, item) {
$.each(item, function(k, v) {
output[i] = "household_" + index + "_" + v.id;
i++;
});
});
output;
produces this:
["household_foo_1", "household_foo_3", "household_bar_2", "household_bar_4"]
I get the strings I need; I can take it from here.

Preserving order of an associative PHP array while passing it to javascript through ajax

So Here is my php file code
GetUserArray.php
$Users = array('7'=>'samei', '4'=>"chaya", '10'=>'abetterchutia');
echo json_encode($Users);
and this is my ajax request
$.ajax({
url: './GetUserArray.php',
type: 'POST',
dataType: "json",
success: function(users) {
console.log(users);
$.each( users, function( key, value ) {
console.log(key, value);
});
}
});
now what it gives me is in the console is an object sorted by the keys of that array while i want the orignal order which was 7 4 10 in my php file
Object {4: "chaya", 7: "samei", 10: "abetterchutia"}
4 chutiya
7 sali
10 abetterchutia
The problem with using hashmaps is that they don't actually specify order. Though, in PHP, an array is actually an ordered hashmap, so it does. Once you translate that into an object in Javascript, the order is no longer preserved. The only way to guarantee order in Javascript is to use an array.
So in PHP this works as expected and preserves order.
$arr = [4 => "I'm first", 1 => "I'm second", 3 => "I'm third"];
foreach($arr as $value) {
echo $value, "\n";
}
Which gives us
I'm first
I'm second
I'm third
But encode that to Javascript Object Notation (i.e. JSON) and you get an object, because in Javascript arrays don't have keys, they have indexes.
echo json_encode($arr);
Gives us...
{"4":"I'm first","1":"I'm second","3":"I'm third"}
If you tried to do the same in Javascript with this object you might not get the same order
var obj = {"4":"I'm first","1":"I'm second","3":"I'm third"};
var s = "";
for(var x in obj) {
s += + obj[x] + "\n";
}
document.write("<pre>" + s + "</pre>");
This might give you something more like...
I'm second
I'm third
I'm first
So the only way to fix that is to use an array...
json_encode(array_values($arr));
Now this gives us...
["I'm first","I'm second","I'm third"]
And the order is maintained.
However, if you want to preserve the keys as well, you'll have to create an array of objects.
$json = [];
foreach($arr as $key => $value) {
$json[] = [$key => $value];
}
echo json_encode($json);
Now you get...
[{"4":"I'm first"},{"1":"I'm second"},{"3":"I'm third"}]
Which in javascript, works perfectly as expected...
for(var x in obj) {
for(var n in obj[x]) {
obj[x][n]; // now you can both maintain order and have access to the key
}
}

How to use complex data structures to populate a div or table in JavaScript & jQuery

I need help understanding the best way to manipulate a JavaScript data structure (if you call it that?). I come from a Perl background and am trying to iterate through a JavaScript data structure to update a div (or table) on the fly. Currently I'm just making the data a variable (data) to get going. once I have that sorted then I will use jquery's ajax methods to get the data as a json object on the fly. It's my understanding that the data structure I'm currently generating is the same thing I would get if it were json?? if not then I guess thats another question..
I have searched many times for such a tutorial but they are all close but haven't found one that meets my needs...
I would like to in the future be able to re-order the array and repopulate the #data_table div so part of my question is: is this even the best way to represent the data? Then I want to update just one part of the array like a companies phone number or add a person then redraw the div from this updated array...
The end result to the user could look like:
Company: 99 Beans, Auckland, Ph: 360499
People:
Matt, 6471
Christiaan, 6472
Michelle, 6473
Judy, 6474
Company: ....
* Next company and so forth..
My code so far is like this (except I have 500+ entries in the data array and only 2 here):
I have taken some of this code from another question I found here and tried to make it work for my type of structure..
<script>
$(document).ready(function() {
var r = new Array();
var data= [
{
"id":"6477",
"c":"99 Beans",
"ci":"Auckland",
"p":"09 360499",
"co":[
{"id":"6471","c":" NZ", "n":"Matt" },
{"id":"6472","c":" NZ", "n":"Chrstiaan" },
{"id":"6473","c":" NZ", "n":"Michelle" },
{"id":"6474","c":" NZ", "n":"Judy " },
{"id":"6475","c":" NZ", "n":"Kate " },
{"id":"6476","c":" NZ", "n":"Unknown Person" }
]
},
{"id":"7145", "c":"A1 Ltd", "ci":"Te Puke ","p":"06 870090",
"co":[{"id":"7145","c":" NZ", "n":"Alan" }
]
},
];
// this alert used to work, when I had the data as an array of arrays so there must be a problem with how I'm referencing it or my data structure is wrong??
alert (data.length + " companies" );//+ data[455].co[0].n);
var j = -1;
for (var key=0, size=data.length; key<size; key++) {
// first div
r[++j] ='<div>';
r[++j] = data[key].id;
r[++j] = ' - ';
r[++j] = data[key].c;
r[++j] = ' - ';
r[++j] = data[key].p;
r[++j] = '<br />';
//inner div
var k = -1 ;
for (var key1=0, size1=data[key].d.length; key1<size1; key1++) {
r[++j] ='<div>';
r[++j] = data[key].d.[key1].n + ' - ' + data[key].d.[key1].c + ' - ';
r[++j] = '</div>';
}
r[++j] = '</div>';
}
$('#data_table').html(r.join(''));
});
</script>
<div id="data_table"></div>
JSON's representation in Javascript is a javascript object.
var json = {
my_property: 2,
another_property: 'string!'
}
You can then fetch properties with json.my_property or json['my_property'] (which is nice if you don't know what exactly you are fetching, you can do var something = 'something-the-user-selected'; json[something]).
So, with jQuery, you would so something like this:
var json = {}; // get this from the server using $.AJAX() or $.getJSON()
$("#my_table").append("<tr><td>" + json.my_property + "</tr></td");
Or, if you got an array of, say, tweets, you should iterate over them, maybe with underscore's each, jQuery's each or plain old for (var i = 0; i < json.tweets.length; i++).
The data structure you are referring to is JSON.
With jQuery you can easily iterate your data structure with .each() and treat the returned value as an object with the attributes defined.
Here is a sample making the an Ajax call that will build your JSON object and iterating:
$.ajax({
type: "POST",
url: "MySite/MyResource",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
if(data.d.length > 0){
$(data.d).each(function(){$('#mytable').append("<tr><td>Company: " + this.c + "</td></tr>");});
}
},
error: function (xhr, status, error) {
// do something appropriate
}
});
If you are looking to iterate farther then you can continue to call .each()
If data is your JSON value, this will format your specified string. (You'll have to JSONify your string to create it as the actual JSON object)
data.each(function(){
$('#mydiv').append('Company: ' + this.c + ', ' + this.ci + ', Ph: ' + this.p + ' People: ');
this.co.each(function(){$('#mydiv').append(this.n + ', ' + this.id);});
});
For the "rendering an JSON object to HTML", you may want to have a look at jQuery.template() which allows to render pieces of HTML with a template syntax. I have never used it so I do not know how well it can perform with very big lists... (also note that it is still in beta)
UPDATE
Here is a working example (it might not be optimal or anything) but you should see the general idea ;)
http://jsfiddle.net/tsimbalar/A9uYP/
UPDATE 2 for sake of completeness and traceability
There was a syntax error in the original code which prevented the alert() from executing (and all following code).
See comment :
Your code is not working because of a syntax error in
data[key].d.[key1].n., which is invalid syntax. (it should be data[key].d[key1].n, I suppose. Use the Firebug extension ofr Firefox to detect this kind of issues that would otherwise go unnoticed.
After fixing this typo, it is easy to iterate over the contents of the object using jQuery.each() as mentioned by catalpa in another answer. You can then build HTML elements (i.e. $("<div/>")) and append them to existing items of the page with append() . (see the fiddle about that part)
handlebars js templating is far better than jquery template and can be used for rendering complex json objects in html

How to loop through an JSON associative array in javascript?

I'm getting a JSON response from the server and i have to loop through the array in javascript and get the values. But I cant seem to loop throught it.
The JSON response of the array looks like this:
{
   "1": "Schools",
   "20": "Profiles",
   "31": "Statistics",
   "44": "Messages",
   "50": "Contacts"
}
I just want to loop through it to get the ID and Name and populate some values on the page.
I have tried:
$.each(response, function(key, value) {
alert(key + ' ' + value);
});
// and
for (var key in response) {
alert(key + ' ' + response[key]);
}
But neither give the right values.
Thanks in advance for any help.
Reply:
Hi,
The response I'm getting with the second loop is:
0 {
1 "
2 1
3 "
4 :
5 "
6 S
etc etc
So that means its going through the whole response as a string and spliting it as key/value.
Thanks
Your problem is that you are not parsing the JSON string. Therefore, your foreach is going through the characters in the JSON string.
// If you are using jQuery.ajax, you can just set dataType to 'json'
// and the following line will be done for you
var obj = jQuery.parseJSON( response );
// Now the two will work
$.each(obj, function(key, value) {
alert(key + ' ' + value);
});
for (var key in obj) {
alert(key + ' ' + response[key]);
}
var response = {"1":"Schools","20":"Profiles","31":"Statistics","44":"Messages","50":"Contacts"};
for (var i in response) {
console.log(i + ' ' + response[i]);
}
Works just fine, how are you getting your response var?
You don't need to do like that, dealing with string is a boring job. You can make a object through the response.
1:json = eval(xmlHttp.responseText);
but this is unsafe in some degree.
json = JSON.parse(xmlHttp.responseText, function(key,value){// can do some other stuff here.});
then you can operate the variable as a normal object like this obj.a or obj["a"].
May this will help you.
http://jsfiddle.net/sG5sF/
jQuery.each works fine. So is for-each loop
http://jsfiddle.net/TfjrS/
Both of them work as they should. You might have errors in other parts of your code. Is the response variable set correctly to the JSON object given in your question? Are you checking the response statusCode? it should be 200 for a successful response?
Consider looking at How can I parse a JavaScript object with jQuery for a possible answer.
You can use for-in construct in pure Javascript. Of course, you need to be careful that you're only looking at the object's own properties (libraries like Prototype tend to pollute):
for(var key in response) {
if(response.hasOwnProperty(key)) {
...
}
}
EDIT
Are you using jQuery.ajax? What's the dataType value? It should be json. This might be why your response is being interpreted as a string. Also, when you console.log response, does it show up as a string or an object?

Categories