Angular orderBy number sorting as text in ng-repeat

前端 未结 7 1449
天命终不由人
天命终不由人 2020-11-29 08:10

I have this data:

[{\"id\":\"42\",\"firstname\":\"Sarah\",\"lastname\":\"Dilby\",\"age\":\"40\",\"cars\":\"Yaris\"},
{\"firstname\":\"Jason\",\"lastname\":\"         


        
相关标签:
7条回答
  • 2020-11-29 08:31

    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>
    
    0 讨论(0)
  • 2020-11-29 08:36

    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);
    });
    
    0 讨论(0)
  • 2020-11-29 08:41

    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.

    0 讨论(0)
  • 2020-11-29 08:43

    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)

    0 讨论(0)
  • 2020-11-29 08:47

    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.

    0 讨论(0)
  • 2020-11-29 08:48

    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';
        }
    };
    
    0 讨论(0)
提交回复
热议问题