Jason Gray Jason Gray - 4 years ago 117
Javascript Question

Angular JS Form: ng-options and complex option manipulations

I'm having some trouble with a few different select boxes.




Issue #1

First is a box that lists physical locations grouped by either "In state" or "Out of state". I have them grouped and the value and label set the way I want but I cannot get the grouped options to sort alphabetically. I've tried orderBy:'name' and other solutions that seem to work for everyone else.

My html looks like this:

<select name="dealer" id="dealer" ng-model="warrantyReg.dealer" ng-options="dealer as dealer.selectLabel group by dealer.for for dealer in dealers track by dealer.selectValue | orderBy:'selectLabel'">


A few examples from my dealers array:

$scope.dealers = [
{selectLabel:"Location A", selectValue:255, for:"In state"},
{selectLabel:"Location C", selectValue:1, for:"In state"},
{selectLabel:"Location B", selectValue:5, for:"In state"},
{selectLabel:"Location Z", selectValue:25, for:"Out of state"},
{selectLabel:"Location X", selectValue:55, for:"Out of state"},
{selectLabel:"Location Y", selectValue:50, for:"Out of state"}
];


(Please note that this is a dumbed down version of the objects, they contain a lot more information than I'm showing here.)

No matter what I do the options are never sorted by the selectLabel. I've also tried orderBy:'dealer.selectLabel' and it does nothing as well.

UPDATE
I forgot to mention that $scope.dealers is being built by an angular.forEach() on data returned by a service. I loop through each returned dealer and create selectLabel by concatenating the name and location keys then pushing that value into the $scope.dealers array.

Using .sort() on $scope.dealers does nothing. However if I use .sort() on the data returned from the service before passing it through the angular.forEach() it does sort them. I'm not sure what the difference is but that's at least a kind of solution and is what I'm doing for now.




Issue #2

I want a select box with an "other..." option that provides a text field when it is selected. That part I have working but I cannot get the "other..." option to display at the bottom of the list of items if I group any of the options together.

For instance I have this data set:

$scope.refs = [
{name:'Friend'},
{name:'Walk-in'},
{name:'Yellow pages'},
{name:'Field and Stream', type:'Magazines'},
{name:'Parent', type:'Magazines'},
{name:'Guns & Ammo', type:'Magazines'},
{name:'other...'}
];


Using that example, "other..." always appears between "Yellow pages" and the "Magazines" group heading.

Additionally, I have another data set that has two sets of grouped items with an "other..." option that isn't grouped and it displays the "other..." option above both groups.

Is there any way to position just the "other..." option at the bottom of a list with grouped items?

UPDATE
Since it seems there is no solution for this one I will just make the options static html instead of relying on ng-options to generate them. I could then put the code into an include if it's a select field that is going to be used in multiple places.

Answer Source

Issue #1

Why not sort the values in the controller like so:

$scope.dealers = [
    {selectLabel:"Location B", selectValue:255, for:"In state"},
    {selectLabel:"Location C", selectValue:1, for:"In state"},
    {selectLabel:"Location A", selectValue:5, for:"In state"},
    {selectLabel:"Location Z", selectValue:25, for:"Out of state"},
    {selectLabel:"Location X", selectValue:55, for:"Out of state"},
    {selectLabel:"Location Y", selectValue:50, for:"Out of state"}
].sort(function(a,b){ 
    return a.selectLabel.localeCompare(b.selectLabel); 
});

Issue #2

Seems that it's not possible. See this answer.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download