ryvantage
ryvantage

Reputation: 13486

Prevent Javascript from reordering JSON

I have these two JSON maps:

{
  "1000006": "Alternate Business Phone",
  "1000008": "Alternate Home Phone",
  "1000001": "Business Phone",
  "1000003": "Clinic Phone",
  "3": "Facsimile",
  "1000007": "Home Phone",
  "1000004": "Lab Phone",
  "4": "Pager",
  "1000002": "Secure Msg Phone"
}

and

{
  "6": "Business Email",
  "1000005": "Deliver To Email",
  "7": "Personal Email"
}

Which are key-value maps alphabetized by value. I am using these two to change the contents of a drop-down menu based on another drop-down's selected item. Pics to illustrate:


Phone selected:

enter image description here


Email selected:

enter image description here


But, as you can see in the image, the order of the list items is not being preserved.

My Javascript handling the list items is this:

  var options_1 = {"1000006":"Alternate Business Phone","1000008":"Alternate Home Phone","1000001":"Business Phone","1000003":"Clinic Phone","3":"Facsimile","1000007":"Home Phone","1000004":"Lab Phone","4":"Pager","1000002":"Secure Msg Phone"};
  var options_2 = {"6":"Business Email","1000005":"Deliver To Email","7":"Personal Email"};
  function changePhoneEmailItems()
  {
    var selectedItem = document.getElementById("addNewCategory").value;
    var options;
    if('1' === selectedItem) {
        options = options_1;
    } else {
        options = options_2;
    }
    var list = document.getElementById("addNewUsageType");
    list.options.length=0;
    for(var i in options) {
        list.add(new Option(options[i], i));
    }
  }

According to this StackOverflow answer, I need to change the data structure I'm using because JSON is, by definition, unordered.

I tried changing the JSON to a new Map:

var options_1 = {"1000006":"Alternate Business Phone","1000008":"Alternate Home Phone","1000001":"Business Phone","1000003":"Clinic Phone","3":"Facsimile","1000007":"Home Phone","1000004":"Lab Phone","4":"Pager","1000002":"Secure Msg Phone"};
var options_2 = {"6":"Business Email","1000005":"Deliver To Email","7":"Personal Email"};
var options_1_map = new Map(options_1);
console.log(options_1_map);

But it threw an error:

TypeError: options_1 is not iterable

How do I change the JSON object to preserve the original order?

NOTE: My JSON is coming from a Spring controller which is "wrapping" the map in JSON to send to the view. But I am able to modify the controller if there is a more sensible way to transfer the map from the controller to the view.

EDIT: For good measure, the controller code that is generating the JSON is:

for(int i = 1; i <= 2; i++) {
    JsonObject json = new JsonObject();
    HashMap<String, String> CDCONTMETHTP = (HashMap<String, String>)model.get("CDCONTMETHTP_" + i);
    for(Entry<String, String> option : CDCONTMETHTP.entrySet()) {
        json.addProperty(option.getKey(), option.getValue());
    }
    model.put("options_" + i, json);
}

Which I am able to modify if need be.

Upvotes: 3

Views: 1513

Answers (2)

ryvantage
ryvantage

Reputation: 13486

David's answer worked, but not without modifying the for loop that iterated through the elements. I have posted the full solution here:

var options_1 = {"1000006":"Alternate Business Phone","1000008":"Alternate Home Phone","1000001":"Business Phone","1000003":"Clinic Phone","3":"Facsimile","1000007":"Home Phone","1000004":"Lab Phone","4":"Pager","1000002":"Secure Msg Phone"};
var options_2 = {"6":"Business Email","1000005":"Deliver To Email","7":"Personal Email"};
function changePhoneEmailItems()
{
    var selectedItem = document.getElementById("addNewCategory").value;
    var options;
    if('1' === selectedItem) {
        options = options_1;
    } else {
        options = options_2;
    }

    var list = document.getElementById("addNewUsageType");
    list.options.length=0;
    Object.keys(options).forEach(function(i) {
        list.add(new Option(options[i].value, options[i].key))          
    });
}

Upvotes: 0

Davi
Davi

Reputation: 4147

Your JSON maps are key-value pairs and there is no way to preserve the ordering of keys. You can convert your JSON maps to Arrays, which will preserve the order.

Instead of this JSON:

{
  "6": "Business Email",
  "1000005": "Deliver To Email",
  "7": "Personal Email"
}

Send this JSON:

[
  {"id": 6, "text": "Business Email"},
  {"id": 1000005, "text": "Deliver To Email"},
  {"id": 7, "text": "Personal Email"}
]

Upvotes: 7

Related Questions