Natural Sort in Angular JS
Article Purpose
The purpose of this article is to showcase the Angular JS natural sort solution of Ben Nadel and Phil DeJarnett. In addition, I propose an improvement that accounts for using natural sort against an array of objects by property name.
Problem
In a recent project, I needed to improve the alphanumeric sorting of a product list as it didn’t sort the numbered products as one would expect. For example the sort would result in:
- 300
- 3000
- 310
When the expectation is:
- 300
- 310
- 3000
Upon some investigation, I found myself on Ben Nadel’s User-Friendly Sort Of Alpha-Numeric Data In JavaScript blog post. After reading it and then the comments, I found out the term I was looking for is natural sort (thanks Sean Coyne). In addition, I was able to see that Phil DeJarnett improved upon Ben’s solution a great deal. That solution and the description of why the sorting doesn’t occur as you’d expect is found in Phil’s blog post Natural Sorting with Angular.js.
Phil’s solution is excellent, but it fell slightly short for me. The issue I ran into after implementing Phil’s solution was that it didn’t allow for the sorting of an array of objects by property name. It assumed the array to sort was a list of strings.
Solution
Through digging into the source code, I was able to quickly determine what changes were needed. The edits I made are small and quite simple too. In fact there are only two core changes:
- I wrap the natural sort function in another function adding the ability to pass an optional argument while ensuring the original sort function returns.
- I use bracket notation in combination with the ternary operator to succinctly update the sort using the aforementioned property name argument if it exists. Otherwise the sort occurs as originally designed.
That’s it. These two additions now make it possible to leverage natural sort on an array of objects by property name.
Code
Before - naturalSortVersionDatesCaching.js
Before Usage
After
After Usage
If you have improvement ideas or any other thoughts, just reach out on Twitter @derekknox or email me derek [at] derekknox.com.