角orderBy数字排序作为ng-repeat中的文本

时间:2022-12-02 17:09:33

I have this data:

我有这个数据:

[{"id":"42","firstname":"Sarah","lastname":"Dilby","age":"40","cars":"Yaris"},
{"firstname":"Jason","lastname":"Diry","age":"5","id":"5"},
{"id":"6","firstname":"Bilson","lastname":"Berby","age":"1","cars":"Tipo"}]

When I orderBy id or by age in an ng-repeat, it sorts the number as text. Since I can't find it written that this is an issue anywhere, I'm guessing there's a problem with my code. I have created this fiddle: http://jsfiddle.net/vsbGH/1/ Sorry about the template, but jsfiddle doesn't allow in the html box. Anyway, this is the code which loads and sorts the data:

当我使用id或按年龄进行ng-repeat时,它将数字排序为文本。因为我找不到它写的这是一个问题,我猜我的代码有问题。我已经创建了这个fiddle: http://jsfiddle.net/vsbGH/1/对不起,关于模板,但是jsfiddle不允许在html框中使用。不管怎样,这是加载和排序数据的代码:

//user data
app.service('People', function() {
var People = {};
People.details = [{"id":"42","firstname":"Sarah","lastname":"Dilby","age":"40","cars":"Yaris"},
                  {"firstname":"Jason","lastname":"Diry","age":"5","id":"5"},
                  {"id":"6","firstname":"Bilson","lastname":"Berby","age":"1","cars":"Tipo"}]
return People;
});

//list ctrl
controllers.listCtrl = function ($scope,People) {
 $scope.people = People.details;

 $scope.sortList = function(sortname) {
    $scope.sorter = sortname;
 }
}

And this is the ng-repeat part of the template:

这是ng-repeat模板的一部分:

<tr ng-repeat="person in people | orderBy:sorter ">
        <td>{{person.id | number}}</td>
        <td>{{person.firstname}} </td>
        <td>{{person.lastname}} </td>
        <td>{{person.age | number}}</td>
        <td>{{person.cars}} </td>
 </tr>

Many thanks if you can help me understand why the number data isn't sorting as numbers, and why it's sorting as text.

非常感谢,如果您能帮助我理解为什么数字数据不是作为数字排序,以及为什么它作为文本排序。

7 个解决方案

#1


48  

I think the most appropriate solution is to format the numbers I have on my JSON objects correctly, ie not to wrap them in quotes. So:

我认为最合适的解决方案是正确地格式化JSON对象上的数字(不要用引号括起来)。所以:

 [{"id":"42","firstname":"Sarah","lastname":"Dilby","age":"40","cars":"Yaris"},
  {"firstname":"Jason","lastname":"Diry","age":"5","id":"5"},
  {"id":"6","firstname":"Bilson","lastname":"Berby","age":"1","cars":"Tipo"}]

becomes:

就变成:

[{"id":42,"firstname":"Sarah","lastname":"Dilby","age":40,"cars":"Yaris"},
 {"firstname":"Jason","lastname":"Diry","age":5,"id":5},
 {"id":6,"firstname":"Bilson","lastname":"Berby","age":1,"cars":"Tipo"}]

I'm guessing SergL's solution is good if it's not possible to correct the format of the JSON data.

如果无法纠正JSON数据的格式,我猜想SergL的解决方案是好的。

To add to this, the issue in my specific case is to do with PHP's json_encode function on the server side. By default, it treats numbers as strings. To fix I had to add the JSON_NUMERIC_CHECK option to the encode method in the PHP script:

为此,在我的具体情况中,问题是在服务器端使用PHP的json_encode函数。默认情况下,它将数字视为字符串。为了修复,我必须将JSON_NUMERIC_CHECK选项添加到PHP脚本中的编码方法:

json_encode($assoc_array,JSON_NUMERIC_CHECK);

#2


26  

You don't have to modify your JSON. You can pass a function to orderBy filter like this:

不需要修改JSON。您可以将一个函数传递给orderBy过滤器,如下所示:

$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>

#3


15  

Inside your ng-repeat directive you are using a number filter

在你的ng-repeat指令中,你正在使用数字过滤器

<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.

过滤器用于格式化输出,但它们不更新模型属性。例如:人。id = 1234.56789将被渲染为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:

如上所述,您必须将年龄转换为类型号。然后orderBy就会正常工作。例如在你的服务中:

angular.forEach(People.details, function (detail) {
  detail.age = parseFloat(detail.age);
});

#4


5  

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.

如果您的orderBy值不是指向另一个字符串的变量,而是您要排序的属性,那么必须将其放在引号中。

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)

如果,在解析了int或float之后,仍然没有进行正确的排序,这可能是因为这个原因。(那是我的笨蛋帽子)

#5


3  

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.

当我使用文本字段和ngModel来改变我所订购的模型的值时,我遇到了同样的问题。因为这个值被认为是字符串。

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.

使用新的HTML5 ,角将输入字段的值解析为一个数字(我认为是浮点数),这帮助我得到了正确的顺序。

#6


0  

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.

让orderBy指向由范围或它不是孤立的祖先所拥有的方法,并让该方法返回从字符串中提取的数字。您可能需要编写一个指令来继承由ngRepeat实例创建的person范围。添加这个方法。

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.

如果无法更改数据服务器端,则在获取时更改它的客户端。

#7


-1  

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.

当调用排序函数时,最好更新重复集合。这里我使用了Lodash - orderBy,只是为了根据排序器函数对集合进行排序。假设在单击表列头时调用排序。

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';
    }
};

#1


48  

I think the most appropriate solution is to format the numbers I have on my JSON objects correctly, ie not to wrap them in quotes. So:

我认为最合适的解决方案是正确地格式化JSON对象上的数字(不要用引号括起来)。所以:

 [{"id":"42","firstname":"Sarah","lastname":"Dilby","age":"40","cars":"Yaris"},
  {"firstname":"Jason","lastname":"Diry","age":"5","id":"5"},
  {"id":"6","firstname":"Bilson","lastname":"Berby","age":"1","cars":"Tipo"}]

becomes:

就变成:

[{"id":42,"firstname":"Sarah","lastname":"Dilby","age":40,"cars":"Yaris"},
 {"firstname":"Jason","lastname":"Diry","age":5,"id":5},
 {"id":6,"firstname":"Bilson","lastname":"Berby","age":1,"cars":"Tipo"}]

I'm guessing SergL's solution is good if it's not possible to correct the format of the JSON data.

如果无法纠正JSON数据的格式,我猜想SergL的解决方案是好的。

To add to this, the issue in my specific case is to do with PHP's json_encode function on the server side. By default, it treats numbers as strings. To fix I had to add the JSON_NUMERIC_CHECK option to the encode method in the PHP script:

为此,在我的具体情况中,问题是在服务器端使用PHP的json_encode函数。默认情况下,它将数字视为字符串。为了修复,我必须将JSON_NUMERIC_CHECK选项添加到PHP脚本中的编码方法:

json_encode($assoc_array,JSON_NUMERIC_CHECK);

#2


26  

You don't have to modify your JSON. You can pass a function to orderBy filter like this:

不需要修改JSON。您可以将一个函数传递给orderBy过滤器,如下所示:

$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>

#3


15  

Inside your ng-repeat directive you are using a number filter

在你的ng-repeat指令中,你正在使用数字过滤器

<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.

过滤器用于格式化输出,但它们不更新模型属性。例如:人。id = 1234.56789将被渲染为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:

如上所述,您必须将年龄转换为类型号。然后orderBy就会正常工作。例如在你的服务中:

angular.forEach(People.details, function (detail) {
  detail.age = parseFloat(detail.age);
});

#4


5  

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.

如果您的orderBy值不是指向另一个字符串的变量,而是您要排序的属性,那么必须将其放在引号中。

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)

如果,在解析了int或float之后,仍然没有进行正确的排序,这可能是因为这个原因。(那是我的笨蛋帽子)

#5


3  

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.

当我使用文本字段和ngModel来改变我所订购的模型的值时,我遇到了同样的问题。因为这个值被认为是字符串。

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.

使用新的HTML5 ,角将输入字段的值解析为一个数字(我认为是浮点数),这帮助我得到了正确的顺序。

#6


0  

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.

让orderBy指向由范围或它不是孤立的祖先所拥有的方法,并让该方法返回从字符串中提取的数字。您可能需要编写一个指令来继承由ngRepeat实例创建的person范围。添加这个方法。

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.

如果无法更改数据服务器端,则在获取时更改它的客户端。

#7


-1  

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.

当调用排序函数时,最好更新重复集合。这里我使用了Lodash - orderBy,只是为了根据排序器函数对集合进行排序。假设在单击表列头时调用排序。

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';
    }
};