0

This is a very strange issue.

I am calling a server side method to return an array of suburbs which have been sorted alphabetically.

When I hit the end-point directly, the order is as expected. However, when Jquery calls the method, it is returned in a random order...

I suspect the issue is to do with the jquery function:

function updateSuburbs(suburb_selected,town_id)
{
    var $suburbs = $("#mds_suburbs");
    $suburbs.empty();
    $suburbs.append($("<option></option>").attr("value", "").text('Loading...'));
    url = '/api/rpc/delivery/engine/suburbs/town_id/' + town_id;
    $.ajax({
        type:  'GET',
        async: true,
        url:   url,
        dataType: "json",

        success: function(responseObject){

            $suburbs.empty();
            $suburbs.append($("<option></option>").attr("value", "").text('Select your suburb'));
            if (responseObject.status) {
                if (responseObject.suburbs) {
                    $.each(responseObject.suburbs, function(value,key) {
                        $suburbs.append($("<option></option>").attr("value", value).text(key));
                    });
                    if (suburb_selected !== null && suburb_selected !== '')
                    {
                        $('#mds_suburbs').val(suburb_selected);
                    }
                } else {
                    $suburbs.append($("<option></option>")
                        .attr("value", 0).text('No suburbs for this town...'));
                }
            } else {
                $suburbs.empty();
                $suburbs.append($("<option></option>").attr("value", "").text('Error locations suburb'));
            }
        }
    });
}

EIDT:

Further reading and research suggests that it is infact Chrome that is automatically sorting the object array... :S

Server side output:

enter image description here

Client side output:

enter image description here

5
  • 1
    Can your provide a sample of the object? I suspect it is not an array, but an object, and then the reason is that object properties do not have a predefined order. Commented Apr 6, 2017 at 17:50
  • I have added some screenshots of the server side output and the client side output... Commented Apr 6, 2017 at 17:56
  • 1
    It confirms what I said: these are not arrays for JSON, even though in PHP they are called associative arrays. They are non-array objects in JSON and JavaScript. Commented Apr 6, 2017 at 17:58
  • ok - what would be the best way to sort this? Commented Apr 6, 2017 at 18:02
  • Do you have control over the PHP code, and if so, could you consider changing the data structure there? Or is that not an option? NB: It would be more useful if you would include the text version of the data structures, not images. Commented Apr 6, 2017 at 18:03

1 Answer 1

1

It may be misleading that this data structure is represented as an array in PHP. But it is important to note that even in PHP they are not called indexed arrays with numerical indexes starting at 0, but associative arrays.

These translate to non-array objects in JSON, and likewise in JavaScript. Properties of non-array objects have no predefined order in JavaScript, so they can come out in unpredictable orders, which may be browser dependent.

See "Does JavaScript Guarantee Object Property Order?" for more information.

Solution

In PHP you could convert the associative array to an indexed array:

Instead of:

$suburbs = Array(
    "5190" => "CBD",
    "5823" => "Cloetsville",
    "5984" => "De Zalze"
)

Get this structure:

$suburbs = Array(
    0 => Array("code" => "5190", "name" => "CBD"),
    1 => Array("code" => "5823", "name" => "Cloetsville"),
    2 => Array("code" => "5984", "name" => "De Zalze")
)

This conversion you can do with this PHP code:

foreach($suburbs as $key => $value) {
    $result[] = ["code" => $key, "name" => $value];
}
$suburbs = $result;

... and continue like before to output it as JSON with json_encode.

In JavaScript you'll have to change the $.each callback as follows:

$.each(responseObject.suburbs, function(i, value) {
    $suburbs.append($("<option></option>")
            .attr("value", value.code).text(value.name));
});
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your solution!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.