0

I am working with a table that has several orderable columns. The columns can be ordered in both ASC and DESC ways. Some of the columns contain strings and some numbers. The problem is, that my data contains a lot of null values. Therefore, when sorting (ASC with strings or DESC with numbers) I first get a long list of nulls and then see the actual values at the bottom. This is why I'm looking for a way to put the null values always at the bottom.

I've already checked many stackoverflow questions like Angular Sorting with null objects, AngularJS orderby with empty field, and AngularJS sorting a list with nulls, but none of these seem to work in this case.

Here is a small example of what I'm working with:

var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.result = [ {
        "value11": 17,
        "value12": 34522342,
        "value2": "a",
        "value3": 4
    },
  {
        "value11": 17,
        "value12": 23453345,
        "value2": "c",
        "value3": null
    },
  {
        "value11": 16,
        "value12": 43553234,
        "value2": null,
        "value3": null
    },
  {
        "value11": 17,
        "value12": 23546324,
        "value2": null,
        "value3": 2
    }
];

$scope.sortType = ['value11', 'value12'];

$scope.sortReverse  = false; 

$scope.sortableClass= function(sortColumn){
    var thClass = ['sortable']; 
    var direction = '';
     //if the parameter is name, the sortColumn parameter will be the value1.1 value1.2 array
     if(sortColumn=="name"){
      sortColumn = ['value11', 'value12'];
    }

    //toString is to account for ["value1.1", "value1.2"] array comparison
    if(sortColumn.toString() == $scope.sortType.toString()){
      direction = $scope.sortReverse ? 'asc' : 'desc';
      thClass.push('selectedColumn');
      thClass.push(direction);
    }
    
    return thClass;
  }
  
  $scope.sortTable = function(sortColumn) {
    if(sortColumn == "name"){
      $scope.sortType=['value11', 'value12'];
    } else{
      $scope.sortType=sortColumn;  
    }
    $scope.sortReverse= !$scope.sortReverse; 
  };
  
 });
<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.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
 <table>
  <thead class="ng-scope">
   <tr>
    <th ng-class="sortableClass('name')">
     <a href="#" ng-click="sortTable('name')">Column1</a>
    </th>
    <th ng-class="sortableClass('name')">
     <a href="#" ng-click="sortTable('value2')">Column2</a>
    </th>
    <th ng-class="sortableClass('name')">
     <a href="#" ng-click="sortTable('value3')">Column3</a>
    </th> 
   </tr>
  </thead>
  <tbody>
   <tr ng-repeat="n in result | orderBy:sortType:sortReverse">
    <td data-title="Value1.1 and value1.2">{{n.value11}}:{{n.value12}}</td>
    <td data-title="Value2">{{n.value2}}</td>
    <td data-title="Value3">{{n.value3}}</td>
   </tr>
  </tbody>
 </table>
</div>

Hope that you can help! Many thanks!

Community
  • 1
  • 1

1 Answers1

-1

This is something I tried, but here at least one problem is that obj[$scope.sortType] is undefined. Hopefully this helps with solving the problem.

var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.result = [ {
        "value11": 17,
        "value12": 34522342,
        "value2": "a",
        "value3": 4
    },
  {
        "value11": 17,
        "value12": 23453345,
        "value2": "c",
        "value3": null
    },
  {
        "value11": 16,
        "value12": 43553234,
        "value2": null,
        "value3": null
    },
  {
        "value11": 17,
        "value12": 23546324,
        "value2": null,
        "value3": 2
    }
];

$scope.sortType = ['value11', 'value12'];

$scope.sortReverse  = false; 

$scope.sortableClass= function(sortColumn){
    var thClass = ['sortable']; 
    var direction = '';
     //if the parameter is name, the sortColumn parameter will be the value1.1 value1.2 array
     if(sortColumn=="name"){
      sortColumn = ['value11', 'value12'];
    }

    //toString is to account for ["value1.1", "value1.2"] array comparison
    if(sortColumn.toString() == $scope.sortType.toString()){
      direction = $scope.sortReverse ? 'asc' : 'desc';
      thClass.push('selectedColumn');
      thClass.push(direction);
    }
    
    return thClass;
  }
  
  $scope.sortTable = function(sortColumn) {
    if(sortColumn == "name"){
      $scope.sortType=['value11', 'value12'];
    } else{
      $scope.sortType=sortColumn;  
    }
    $scope.sortReverse= !$scope.sortReverse; 
  };
  
   $scope.nullsToBottom = function(obj) {
    return (angular.isDefined(obj[$scope.sortType]) ? -1 : 0);
  };
  
 });
<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.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
 <table>
  <thead class="ng-scope">
   <tr>
    <th ng-class="sortableClass('name')">
     <a href="#" ng-click="sortTable('name')">Column1</a>
    </th>
    <th ng-class="sortableClass('name')">
     <a href="#" ng-click="sortTable('value2')">Column2</a>
    </th>
    <th ng-class="sortableClass('name')">
     <a href="#" ng-click="sortTable('value3')">Column3</a>
    </th> 
   </tr>
  </thead>
  <tbody>
   <tr ng-repeat="n in result | orderBy:[nullsToBottom].concat(sortType):sortReverse">
    <td data-title="Value1.1 and value1.2">{{n.value11}}:{{n.value12}}</td>
    <td data-title="Value2">{{n.value2}}</td>
    <td data-title="Value3">{{n.value3}}</td>
   </tr>
  </tbody>
 </table>
</div>