fngyo
fngyo

Reputation: 31

AngularJS orderBy on select boxes doesn't work as expected.

I am trying to convert an old PHP/JS project over to straight AngularJS.

The issue I'm running into is that the orderBy:"name" on my select box is only sort of working.

For example, in the plunker (below) if you open the building drop down, it appears to be in the correct alphabetical order. However, there's a few that are just randomly misplaced throughout the drop down.

The other odd thing is that the JSON file is already in alphabetical order, so I'm not sure what the deal is.

I am new to AngularJS, so I know I'm missing something that's small. Any help would be greatly appreciated. Thanks!

Plunker: http://plnkr.co/edit/wHSERdfKLaYaaSMBph73

JSON Example:

{
    "id": 110,
    "name": "Administration Center",
    "address": null,
    "latitude": "41.256326",
    "longitude": "-95.973784",
    "content": "",
    "overlay": "g|xzFnywhQ?^^??j@M??^r@??_@K??kA",
    "url": "",
    "type_id": 3,
    "show_marker": 0,
    "show_label": 1,
    "custom_marker": "",
    "created_at": "2013-07-10 15:40:09",
    "updated_at": "2013-07-10 15:42:50",
    "color": "#08c"
}

Upvotes: 1

Views: 957

Answers (3)

jpmorin
jpmorin

Reputation: 6018

Your plunker had some errors in the order of your dependancies (ie: jquery after angular, etc. There is an error message in the dev console). When using angular and jquery, you have to include jquery first.

<script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script src="http://code.angularjs.org/1.2.0-rc.3/angular.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<script src="//cdn.jsdelivr.net/underscorejs/1.5.1/underscore-min.js"></script>

Here is your demo with the fixes: http://plnkr.co/edit/92zvkjP1cx1wBlGqwB4D?p=preview

You do not need to order your data in the controller if you are using the orderBy filter.

html

<div ng-repeat="(key,menu) in menus">
    <h1>{{typeIds[key]}}</h1>
    <select ng-model="selectedlocation" 
            ng-options="item.id as item.name for item in menu | orderBy:'name'">
    </select>
</div>

js

function menuController($scope, $http) {
    // probably not the best way to do this
    $scope.typeIds = {3: "Buildings", 6: "Parking (Fac/Staff)", 7: "Parking (Public)", 8: "Parking (Student)", 11: "Landmarks"};

    $http.get('locations.json').then(function(res) {
        $scope.locations = res.data;
        $scope.menus = _($scope.locations).groupBy('type_id');

        /*
        // This is not needed anymore
        //Convert to array so it sorts correctly on the view side. 
        $scope.orderedMenus = [];
        _($scope.menus).each(function(data, key) {
            $scope.orderedMenus.push({"key" : key, "data" : data})
        });
        */
    });
}

Upvotes: 1

KayakDave
KayakDave

Reputation: 24676

Looks like there's a better solution posted here now. But, just so you know your options in these situations, you can write you own sort as orderBy can take a sort function, for example:

  <select ng-model="selectedlocation" ng-options="value.id as value.name for (key,value) in menu.data | orderBy:sortFunction"></select>  

If you add something like the following in your controller:

$scope.sortFunction = function(item){
   console.log("Parameter: ", item.name);
}

You'll see you get the item name. If you go this route, your job is to return a value from sortFunction() that when evaluated against the <, =, > operator produces whatever sort you'd like.

I'm not recommending this route- just mentioning it for completeness sake.

http://docs.angularjs.org/api/ng.filter:orderBy

Upvotes: 0

jcollum
jcollum

Reputation: 46599

http://plnkr.co/edit/yRR34nwCBIh6cAiTXIBP?p=preview

It looks to me like ng-select just doesn't like to order on anything but the value (edit: it looks like that's not right exactly). So I did a bit of sorting in the controller with underscore and made a more explicit select:

 <div ng-repeat="menu in orderedMenus | orderBy:'name'"><!-- orderBy might not be necessary here --> 
  <h1>{{typeIds[menu.key]}}</h1>
  <select ng-model="selectedlocation">
   <option ng-repeat="item in  menu" value="item.id">
    {{item.name}}
   </option>
  </select>     
 </div>

Which does the trick. Screenshot here.

Upvotes: 0

Related Questions