Shikha thakur Shikha thakur - 4 months ago 31
AngularJS Question

table sorting using orderBy not working as expected

I need to sort table data for which i used orderBy filter and it is getting sorted from last row above
plunker example will be much explanable

DEMO

html:

<table class="friends">
<thead>
<tr class='table-head'>
<th scope="col">Candidate Name</th>
<th scope="col" ng-repeat="a in [1,2,3,4]" ng-click="sortBy('candidateData.rating')"><a style="cursor:pointer">Round{{a}}</a></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="candidate in aCandidateDetails| orderBy:propertyName:reverse">
<td>
<div>{{candidate.name}}</div>
</td>
<td ng-repeat="candidateData in candidate.ratings">
<div ng-if="candidateData.rating">
{{candidateData.rating}}
</div>
<span ng-if="!candidateData.rating"> - NA - </span> </td>
<td data-title="Status">
<div>{{candidate.interviewStatus}}</div>
</td>
<td><a href="" ng-model='candidate' ng-click="fnCandidateFeedbackDetails(candidate.uniqueId,candidate._id)"><i class="fa fa-info-circle" aria-hidden="true"></i></a></td>
</tr>
</tbody>
</table>


Js:

$scope.propertyName = 'name';
$scope.reverse = true;
$scope.sortBy = function(propertyName) {
$scope.reverse = ($scope.propertyName === propertyName) ? !$scope.reverse : false;
$scope.propertyName = propertyName;
};


Json:

$scope.aCandidateDetails = [{
name: "a",
ratings: [{
round: 1,
rating: 3,
feedback: "something",
interviewer: "abc",
roundStatus: "selected"
},

{
round: 2,
rating: 5,
feedback: "something",
interviewer: "abc",
roundStatus: "selected"
}, {
round: 3,
rating: 4,
feedback: "something",
interviewer: "abc",
roundStatus: "selected"
}, {
round: 4,
rating: 1,
feedback: "something",
interviewer: "abc",
roundStatus: "selected"
}
]
}, {
name: "b",
ratings: [{
round: 1,
rating: 5,
feedback: "something",
interviewer: "abc",
roundStatus: "selected"
},

{
round: 2,
rating: 4,
feedback: "something",
interviewer: "abc",
roundStatus: "selected"
}, {
round: 3,
rating: 3,
feedback: "something",
interviewer: "abc",
roundStatus: "selected"
}, {
round: 4,
rating: 2,
feedback: "something",
interviewer: "abc",
roundStatus: "selected"
}
]
},{
name:"c",
ratings: [{
round: 1,
rating: 1,
feedback: "something",
interviewer: "abc",
roundStatus: "selected"
},

{
round: 2,
rating: 1,
feedback: "something",
interviewer: "abc",
roundStatus: "selected"
}, {
round: 3,
rating: 1,
feedback: "something",
interviewer: "abc",
roundStatus: "selected"
}, {
round: 4,
rating: 1,
feedback: "something",
interviewer: "abc",
roundStatus: "selected"
}]
}]


If we click on round then it should sort based on rating in descending order which is not happening

Any help is appreciated

Answer

You would have to write your own comparator and use it with orderBy. Something like this.

$scope.ratingComparator = function(v1, v2) {
    if (v1.type === 'object') {
      var obj1 = $scope.aCandidateDetails[v1.index];
      var obj2 = $scope.aCandidateDetails[v2.index];
      return (obj1.ratings[$scope.sortRound].rating < obj2.ratings[$scope.sortRound].rating)? -1: 1;
    } else {
      return 1;
    }
  }

And in your html,

<tr ng-repeat="candidate in aCandidateDetails| orderBy:propertyName:reverse:ratingComparator">

Also, because of the structure of your data, you'd have to keep track of the round number by storing it somewhere on the scope. This is because there isn't a separate field for each round. This is accomplished by passing the round number to sortBy

<th scope="col" ng-repeat="a in [1,2,3,4]" ng-click="sortBy('ratings', a)"><a style="cursor:pointer">Round{{a}}</a></th>

Here is the updated Plnkr.

This assumes that ratings array is sorted by round number to start with. If thats not the case, you'd have to add logic in the comparator to search for the round number that was sorted on.