AngularJS orderby with empty field

前端 未结 9 1709
北海茫月
北海茫月 2020-12-05 13:19

I am ordering a my data and its working all correcty except some fields are empty or have no value. When ordered these empty field come up first. For example when ordering n

相关标签:
9条回答
  • 2020-12-05 14:01

    I don't believe there's an "out of the box" solution for this. I could easily be wrong. Here's my attempt at a solution using a function as the predicate:

    ng-repeat="name in names | orderBy:predicate"
    

    Inside your controller:

    $scope.predicate = function(name) {
        return name === '' ? 'zzzzzzz' : !name; 
        /* The 'zzzzzz' forces the empty names to the end, 
          I can't think of a simpler way at the moment. */
    }
    
    0 讨论(0)
  • 2020-12-05 14:03

    Down here! :D

    This solution extends the normal functionality of the angularJs orderBy filter to take a third argument specifying whether or not to invert the normal sorting of null and undefined values. It observes the property names it is passed (not just one), and doesn't iterate over items a second as some of the other solutions do. It's used like this:

    <li ng-repeat="item in (items|orderBy:'name':false:true)">{{item.name}}</li>
    

    I found a bunch of threads, some not directly about orderBy, and compiled their techniques plus a couple bits of my own into this:

    angular.module('lib')
    .config(['$provide', function ($provide) {
        $provide.decorator('orderByFilter', ['$delegate', '$parse', function ($delegate, $parse) {
            return function () {
                var predicates = arguments[1];
                var invertEmpties = arguments[3];
                if (angular.isDefined(invertEmpties)) {
                    if (!angular.isArray(predicates)) {
                        predicates = [predicates];
                    }
                    var newPredicates = [];
                    angular.forEach(predicates, function (predicate) {
                        if (angular.isString(predicate)) {
                            var trimmed = predicate;
                            if (trimmed.charAt(0) == '-') {
                                trimmed = trimmed.slice(1);
                            }
                            var keyFn = $parse(trimmed);
                            newPredicates.push(function (item) {
                                var value = keyFn(item);
                                return (angular.isDefined(value) && value != null) == invertEmpties;
                            })
                        }
                        newPredicates.push(predicate);
                    });
                    predicates = newPredicates;
                }
                return $delegate(arguments[0], predicates, arguments[2]);
            }
        }])
    }]);
    

    To use this code verbatim, be to specify 'lib' as a dependency for your app.

    Credits to:

    • $parse
    • [nullSorter].concat(originalPredicates)
    • decorator pattern
    0 讨论(0)
  • 2020-12-05 14:04

    I created a gist with an alternative filter based on the previous solutions: https://gist.github.com/360disrupt/1432ee1cd1685a0baf8967dc70ae14b1

    The filter extends the existing angular filter:

    angular.module 'tsd.orderByEmptyLast', []
      .filter 'orderByEmptyLast', ($filter) ->
        return (list, predicate, reverse)->
          orderedList = $filter('orderBy')(list, if reverse then ['!' + predicate, '-' + predicate] else ['!' + predicate, predicate] )
          return orderedList
    

    On newer angular versions you might need to include orderByFilter instead of using $filter

    angular.module 'tsd.orderByEmptyLast', ['orderByFilter']
      .filter 'orderByEmptyLast', () ->
        return (list, predicate, reverse)->
          orderedList = orderByFilter(list, if reverse then ['!' + predicate, '-' + predicate] else ['!' + predicate, predicate] )
          return orderedList
    
    0 讨论(0)
提交回复
热议问题