AngularJS

Custom orderBy filter with localeCompare for diacritics support

AngularJS orderBy filter doesn't support ordering with diacritics.

Sometimes you need to sort data which contains diacritics. For example words which contains (š, ř, ž) letters are not ordered properly by original orderBy filter by AngularJS. I have written custom orderBy filter which supports that feature.

 

"use strict";

angular.module("app.filters", [])
    .filter("localeOrderBy", [function () {
        return function (array, sortPredicate, reverseOrder) {
            if (!Array.isArray(array)) return array;
            if (!sortPredicate) return array;

            var isString = function (value) {
                return (typeof value === "string");
            };

            var isNumber = function (value) {
                return (typeof value === "number");
            };

            var isBoolean = function (value) {
                return (typeof value === "boolean");
            };

            var arrayCopy = [];
            angular.forEach(array, function (item) {
                arrayCopy.push(item);
            });

            arrayCopy.sort(function (a, b) {
                var valueA = a[sortPredicate];
                var valueB = b[sortPredicate];

                if (isString(valueA))
                    return !reverseOrder ? valueA.localeCompare(valueB) : valueB.localeCompare(valueA);

                if (isNumber(valueA) || isBoolean(valueA))
                    return !reverseOrder ? valueA - valueB : valueB - valueA;

                return 0;
            });

            return arrayCopy;
        }
    }]);

 

Usage in template.

 

<table class="table">
    <thead>
        <tr>
            <th>First name</th>
            <th>Last name</th>
        </tr>
    </thead>
    <tbody>
        <tr data-ng-repeat="contact in contactList | localeOrderBy:'FirstName'">
            <td>{{contact.FirstName}}</td>
            <td>{{contact.LastName}}</td>
        </tr>
    </tbody>
</table>

 

Now you should see your list properly ordered with diacritics.

 

Update

 

Another way how to solve this problem is to update compare function inside orderByFilter from angular.js source file like below:

function compare(v1, v2){
    var t1 = typeof v1;
    var t2 = typeof v2;
    if (t1 === t2) {
    if (isDate(v1) && isDate(v2)) {
        v1 = v1.valueOf();
        v2 = v2.valueOf();
    }
    if (t1 === "string") {
        v1 = v1.toLowerCase();
        v2 = v2.toLowerCase();
    }
    if (v1 === v2) return 0;
        return v1.localeCompare(v2);
    } else {
        return t1.localeCompare(t2);
    }
}

 

That's all. 

Share on Twitter or Facebook or Google+

Comments

© 2017 JAN HOLINKA