laramit's avatar

List/select box sorting

Hi,

I have a weird problem and am hoping someone can explain it to me but I'm not sure if it's a Laravel issue or JQuery :-)

I have a select box in a view. I'm populating the options for the select box from a database table so I'm pulling out the records I need with:

$companies = Company::orderBy('name')->lists('name', 'id')->toArray();

and then in the view I have:

{!! Form::select('company_id', [null=>'Please Select']+$companies ,null,array('id'=>'companyId')) !!}

Now that all works fine and the companies display in the correct order on the page.

What I'm trying to do now though is use ajax to populate the select box only when a button is pressed on the page. I've set up a route so my ajax request retrieves the companies using the same query as above and the data comes back and populates the select like this:

$.ajax({
        type: "GET",
        url: "/getCompanies",
        async: false,
        success: function (data) {
            $('#companyId').empty()
            $.each(data, function (i,value) {
                $('#companyId').append($('<option>').text(value).attr('value', i));
            });
        }
    });

The data comes back and populates the options through ajax but it is displayed in ID order rather than name order.

So here's where I'm confused! - If I dd($companies) on my original (non ajax) method the records are in ID order there too but they display on the page in name order. The ajax request is getting the same data but when it populates the options they're in ID order.

I'm guessing that maybe when I pass $companies to the view the collection has some kind of ordering meta data that determines how Laravel/Blade displays it but when pulled through ajax I'm just getting an array and it naturally sorts by the key (which is the ID)?

I'm tried all kinds of orderBy, sortBy and changing the sorting position in the chain but I just don't seem able to retrieve a list of IDs and names in name order through an ajax request.

Grateful for any advice!

Thanks, Steve

0 likes
8 replies
ohffs's avatar

Does the jquery .each method not run in parallel - so you have no guarantee what order things might come out? I might be mis-remembering but I think I hit this and realised I had to do a ye-olde for() loop instead. I might be talking nonsense though - it's Friday evening and I'm a bit frazzled ;-)

laramit's avatar

Thanks. After a bit more reading I'm starting to think that too - I'd assumed (a little knowledge is a dangerous thing!) that .each looped through as I know it from PHP. If it's doing them in parallel it's weird how it's always perfectly ordered by ID though every time - unless that's just expected behaviour for .each.

I shall delve deeper into the world of Jquery - or get frazzled too!

ohffs's avatar

@laramit javascript is evil - especially on a Friday... ;-) Still, it's good to have one language out there that makes PHP look sane... ;-)

1 like
thomaskim's avatar

@laramit I don't think it's a jQuery each thing as much as it is a JavaScript issue. For example, open up your console tab and copy/paste this:

var example = {
    19: 'first',
    15: 'second',
    1: 'third',
    8: 'fourth'
};
console.log(example);

It will not preserve the order. You would expect 19 to come first because that's the order you put it in, but you are actually going to get this:

Object {1: "third", 8: "fourth", 15: "second", 19: "first"}

The browser will automatically reorder them. If the key represents a number, the browser will reorder it. Well, I don't know the exact rules, but that's what I've noticed.

If you don't use the toArray() method and just work with the collection, I think it should be fine though and the order will be preserved.

laramit's avatar

Thanks, can't seem to get it to work so far.

.each does loop through each key/value in sequence. I've noticed if I leave out toArray() then the collections is in the correct order but it seems that when the ajax gets collection it's just seen as an indexed array (indexed by ID).

I've tried all kinds of way of sorting both collections and arrays but so far I either get the collection ordered by ID or my ajax just gets [object][object].

I'll keep trying!

thomaskim's avatar

@laramit Once you return a collection, you need to change your jQuery code too. You don't just grab the value now since it's an object. You must now grab the object's name/id like this:

$.each(data, function (i,value) {
    console.log(value.name);
    console.log(value.id);
});
laramit's avatar

Thanks thomaskim, I eventually gave up - however I did it the list was in ID order and I was running out of time so abandoned using jQuery on this.

Please or to participate in this conversation.