1

I've been working on sorting a list of items alphanumerically. I have found that using ng-repeat with orderBy tends to sort either numerically or alphabetically depending on the type of data it is working with. It does not however sort alphanumerically.

JavaScript Code:

    function AppCtrl($scope) {
        $scope.items = [
             {'name':'School Item 1','address':'1920'},
             {'name':'Work Item 2','address':'4192'},
             {'name':'Ad Item 5','address':'2039'},
             {'name':'Cool Item 45','address':'2090'},
             {'name':'Cool Item 50','address':'1029'},
             {'name':'Cool Item 100','address':'1829'},
             {'name':'Cool Item 400','address':'1728'}
        ];
    }

HTML Code:

    <ul ng-controller="AppCtrl">
        <li ng-repeat="item in items|orderBy:['name','address']">
             {{item.name}} {{item.address}}
        </li>
    </ul>

Here is the fiddle http://jsfiddle.net/roverton/PuYLS/1/

Notice that when ordered the it will show 1 then 100, 45 then 400, 5 then 50 etc. I would like to order these alphanumerically. How would I do that in AngularJS?

BrightIntelDusk
  • 4,577
  • 2
  • 25
  • 34
  • Create a custom filter. [This](http://stackoverflow.com/questions/12040395/angularjs-custom-sort-function-in-ng-repeat/12041694#12041694) may also help. – Derek Aug 29 '13 at 17:00
  • If the name is static, you could just add another field to the model for the purposes of sorting and only have the integer value in that field. – Nick Larsen Aug 29 '13 at 17:48
  • Unfortunately the name is not static. It varies from one item to another. I've updated my example to show this. – BrightIntelDusk Aug 30 '13 at 19:31

1 Answers1

1

One way to do this is to use a function to extract the number.

function nameNumberSorter(item) {
    var numberPart = item.name.replace('NamedItem', '');
    return parseInt(numberPart);
}

And then alter your filter a bit:

<div ng-app>
    <ul ng-controller="AppCtrl">
        <li ng-repeat="item in items|filter:deviceBindingFilter|orderBy:nameNumberSorter">
            {{item.name}} - {{item.address}}
        </li>
    </ul>
</div>

Alternatively, you could make an extra field on your model for sorting.

function AppCtrl($scope) {
    $scope.items = [
         {'name':'NamedItem1','address':'1920', 'sortOrder': 1 },
         {'name':'NamedItem2','address':'4192', 'sortOrder': 2 },
         {'name':'NamedItem5','address':'2039', 'sortOrder': 5 },
         {'name':'NamedItem45','address':'2090', 'sortOrder': 45 },
         {'name':'NamedItem50','address':'1029', 'sortOrder': 50 },
         {'name':'NamedItem100','address':'1829', 'sortOrder': 100 },
         {'name':'NamedItem400','address':'1728', 'sortOrder': 400 }
    ];
}

And change your sort to look at this field.

<div ng-app>
    <ul ng-controller="AppCtrl">
        <li ng-repeat="item in items|filter:deviceBindingFilter|orderBy:'sortOrder'">
            {{item.name}} - {{item.address}}
        </li>
    </ul>
</div>
Nick Larsen
  • 18,631
  • 6
  • 67
  • 96
  • I like the solution which you've suggested. Though removing the alphabetical characters would not work. Your solution sorts the items numerically. Is there a way to sort the items alphanumerically? I've updated my question to show what I am talking about. Thanks. – BrightIntelDusk Aug 30 '13 at 19:36
  • In that case, if you know how many digits there will be at a maximum, you can still solve this by replacing all instances of a number by the same number with leading zeros up to the maximum number. I.E. `NamedItem1` would become `NamedItem0001`, and `NamedItem45` would become `NamedItem0045` and `NamedItem400` would become `NamedItem0400`. This replacement is almost as easy as what I have shown above. – Nick Larsen Aug 30 '13 at 19:41
  • 1
    Nick, That will totally work I know exactly how many items will exist in the list. Thank you! :) – BrightIntelDusk Aug 30 '13 at 20:14