I have this data:
[{\"id\":\"42\",\"firstname\":\"Sarah\",\"lastname\":\"Dilby\",\"age\":\"40\",\"cars\":\"Yaris\"},
{\"firstname\":\"Jason\",\"lastname\":\"
You don't have to modify your JSON. You can pass a function to orderBy filter like this:
$scope.sorterFunc = function(person){
return parseInt(person.id);
};
<tr ng-repeat="person in people | orderBy:sorterFunc ">
<td>{{person.id | number}}</td>
<td>{{person.firstname}} </td>
<td>{{person.lastname}} </td>
<td>{{person.age | number}}</td>
<td>{{person.cars}} </td>
</tr>
Inside your ng-repeat directive you are using a number filter
<td>{{person.id | number}}</td>
Filters are used to format the output, but they don't update the Model properties. For example: person.id = 1234.56789 will be rendered as 1,234.568.
As mentioned above you have to convert age to type Number. Then orderBy will work as it should. For example inside your service:
angular.forEach(People.details, function (detail) {
detail.age = parseFloat(detail.age);
});
I faced the same problem when I was working with a text field and ngModel to change the value of the model I was ordering by. Because the value was regarded as string.
With new HTML5 <input type="number" />, Angular parses the value of the input field to a number (float I think), which helped me to get the correct order.
if your orderBy value is not a variable pointing to another string but rather the attribute by which you'll be sorting, you must put it in quotes.
person in people | orderBy:'-id'
If, after you've parsed your int or float and are still not sorting correctly, it might be because of this. <:/ (that's my dunce cap)
Let orderBy point to a method owned by the scope or its not isolated ancestors and let this method return a number casted from the string.
You may have to write a directive inheriting the person scope created by the ngRepeat instances.. to add this method.
Moreover in your case, the age is a string where it could have been an integer and so the numeric sort would be natively applied.
If you cannot change the data serverside then alter it clientside while fetching.
It is best to update your repeating collection whenever a sort function is called. Here I am using Lodash - orderBy just to order the collection based on a sorter function. Lets say the sort is called on click of table column head.
Example:
Collection object:
ctrl.people = [{"id":"42","firstname":"Sarah","lastname":"Dilby","age":"40","cars":"Yaris","salary": 700}, {"firstname":"Jason","lastname":"Diry","age":"5","id":"5","cars":"Lexia","salary": 500},{"id":"6","firstname":"Bilson","lastname":"Berby","age":"1","cars":"Tipo","salary": 400}];
User clicks column head to sort by age:
<th class="col-age" data-ng-click="ctrl.sortColumn('age')">Age</th>
Method called:
ctrl.sortColumn('age'); // where age is column containing numbers only
Method implementation:
ctrl.sortedCol = 'firstname'; //Default sort column
ctrl.sortColumn = (column) => {
ctrl.sortedCol = column; //age
let order = 'asc'; //you can decide the order based on your own logic
ctrl.people = _.orderBy(ctrl.people, [ctrl.sorter], [order]); //update the collection
};
ctrl.sortColumn(ctrl.sortedCol); //called on initial rendering
Sorter function: Returns the sorted collection based on column type
ctrl.sorter = (item) => {
const columnType = ctrl.getColumnType();
if(item[ctrl.sortedCol] && columnType === 'string'){
return item[ctrl.sortedCol].toLowerCase();
} else if(item[ctrl.sortedCol] && columnType === 'number'){
return parseInt(item[ctrl.sortedCol]);
} else{
return item[ctrl.sortedCol];
}
};
Decide column type: Can be string, number or even date
ctrl.getColumnType = () => {
if(ctrl.sortedCol === 'firstname' || ctrl.sortedCol === 'lastname' || ctrl.sortedCol === 'cars'){
return 'string';
} else if(ctrl.sortedCol === 'salary' || ctrl.sortedCol === 'age'){
return 'number';
}
};