Angular Sorting with null objects

前端 未结 4 1177
耶瑟儿~
耶瑟儿~ 2020-12-21 05:39

I need to take records with null values on top , when I\'m sorting by ASC



        
相关标签:
4条回答
  • 2020-12-21 06:13

    I know this is an old post but there is a better way for doing this and could not see it anywhere.

    var myApp = angular.module('myApp', []);
    
    myApp.controller('myCtrl', ["$scope", function($scope){
      $scope.footballers = [
            {id: 0, qt: 13},
            {id: 1, qt: 2},
            {id: 2, qt: 124},
            {id: 3, qt: 12125},
            {id: null , qt: 122},
            {id: 4, qt: -124},
            {id: 5, qt: -5235},
            {id: 6, qt: 43},
            ]
    }]) 
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js"></script>
    
    
    <div ng-app="myApp" ng-controller="myCtrl">
    <div ng-repeat="footballer in footballers | orderBy:['id==null || id']">
        {{footballer.id}}, {{footballer.qt}}
    </div>
    </div>

    One can also use this to show 'id' with any specific value on top of others

    0 讨论(0)
  • 2020-12-21 06:17

    Create a function in the controller that will receive as parameter the entity and will return either ['team.name','id] either [] or other values that will help push the non-sortable elements to top/bottom of the list.

    EDIT (example)

    HTML:

    <li ng-repeat="item in items | orderBy:getItemOrder track by $index">...
    

    AngularJS Ctrl:

    $scope.getItemOrder = function (entity) {
      if (entity.id === null || .... === null) {
        return 0;
      }
    
      return ['team.name','id];
    }
    
    0 讨论(0)
  • 2020-12-21 06:31

    You can use something like this in your controller:

    $scope.nullsToTop = function(obj) {
      return (angular.isDefined(obj.team) ? 0 : -1);
    };
    

    And on the HTML:

    <tr ng-repeat="footballer in footballers | orderBy:[nullsToTop].concat(predicate)">
    

    This way you can maintain your predicate separately. Just concat the nullsToTop function in the orderBy expression to run it first.

    Plunker

    0 讨论(0)
  • 2020-12-21 06:32

    I was able to do it by returning a '+' or a '-' if the value is null, close to what bmleite did but is more contained in the function itself.

    1. create a function that adds a + or a - to the null values depending on the sort order (asc or desc) so that they'd always remain at either the top or bottom

        function compareAndExcludeNull(element){
            var compareWith = $scope.order.propertyName; // in your case that's 'predicate'
    
            var operatorToBottom = $scope.order.reverse ? '+' : '-'; // If decending then consider the null values as smallest, if ascending then consider them biggest
            var operatorToTop = $scope.order.reverse ? '-' : '+';
    
            if(element[compareWith] == null){
                return operatorToTop;
            } else {
                return operatorToBottom+element[compareWith];
            }
        }
    

    if you want to have the null values at the bottom of the sorted array then just switch the operatorToTop with operatorToBottom and vice versa to get:

        function compareAndExcludeNull(element){
            var compareWith = $scope.order.propertyName; // in your case that's '
    
            var operatorToBottom = $scope.order.reverse ? '+' : '-'; // If decending then consider the null values as smallest, if ascending then consider them biggest
            var operatorToTop = $scope.order.reverse ? '-' : '+';
    
            if(element[compareWith] == null){
                return operatorToBottom;
            } else {
                return operatorToTop+element[compareWith];
            }
        }
    

    2. Call the function and pass the array you're sorting

    Javascript:

    In my case I am calling this function from HTML and passing different propertyName depending on the column the user is sorting by, in your case you'd just need to pass 'predicate' as the propertyName

        $scope.order.sortBy = function(propertyName){
            $scope.order.reverse = (propertyName !== null && $scope.order.propertyName === propertyName) ? !$scope.order.reverse : false;
            $scope.order.propertyName = propertyName;
            $scope.resources = $filter('orderBy')($scope.resources,compareAndExcludeNull,$scope.order.reverse);
        };
    

    HTML:

    <div>
        <span ng-if="showKeywords" class="label label-info" ng-click="order.sortBy('keyword')" style="margin-right: 5px">
            Order by Keywords
            <span ng-if="order.propertyName=='keyword'" class="glyphicon glyphicon-triangle-{{order.reverse? 'bottom' : 'top'}}">
            </span>
        </span>
        <span ng-if="showWebsites" class="label label-info" ng-click="order.sortBy('res_title')">
            Order by Website
            <span ng-if="order.propertyName=='res_title'" class="glyphicon glyphicon-triangle-{{order.reverse? 'bottom' : 'top'}}">
            </span>
        </span>
    </div>
    
    0 讨论(0)
提交回复
热议问题