Angularjs 角度orderBy数字排序作为文本在ng repeat中

Angularjs 角度orderBy数字排序作为文本在ng repeat中,angularjs,angularjs-ng-repeat,Angularjs,Angularjs Ng Repeat,我有以下数据: [{"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"}] 当我在ng repeat中按id或年龄排序时,它将数

我有以下数据:

[{"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"}]
当我在ng repeat中按id或年龄排序时,它将数字排序为文本。因为我在任何地方都找不到这是一个问题,所以我猜我的代码有问题。我已经创建了这个fiddle:很抱歉模板,但是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;
 }
}
这是模板的ng重复部分:

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

{{person.id | number}
{{person.firstname}
{{person.lastname}
{{person.age | number}
{{person.cars}}

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

orderBy
指向作用域或其非独立祖先拥有的方法,并让此方法返回从字符串铸造的数字。 您可能需要编写一条指令,继承ngRepeat实例创建的
person
范围。。添加此方法

此外,在您的例子中,年龄是一个字符串,它可能是一个整数,因此数字排序将本机应用


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

在ng repeat指令中,您使用的是数字过滤器

<td>{{person.id | number}}</td>

我认为最合适的解决方案是正确格式化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"}]
变成:

[{"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"}]
如果无法更正JSON数据的格式,我猜SergL的解决方案是好的

除此之外,在我的具体案例中,问题在于服务器端的PHP的json_encode函数。默认情况下,它将数字视为字符串。要修复此问题,我必须在PHP脚本中的encode方法中添加
JSON\u NUMERIC\u CHECK
选项:

json_encode($assoc_array,JSON_NUMERIC_CHECK);

当我使用文本字段和ngModel来更改我订购的模型的值时,我遇到了同样的问题。因为该值被视为字符串

在新的HTML5中,Angular将输入字段的值解析为一个数字(我认为是float),这有助于我获得正确的顺序。

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

person in people | orderBy:'-id'

如果在解析了int或float之后仍然没有正确排序,那么可能是因为这个原因 您不必修改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>
$scope.sorterFunc=功能(个人){
返回parseInt(person.id);
};
{{person.id | number}
{{person.firstname}
{{person.lastname}
{{person.age | number}
{{person.cars}}

每当调用排序函数时,最好更新重复集合。在这里,我使用的只是基于分拣机功能来订购集合。假设在单击表列标题时调用排序

例如:

收集对象:

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}];
用户单击列标题按年龄排序:

<th class="col-age" data-ng-click="ctrl.sortColumn('age')">Age</th>
方法实现:

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
分拣机功能:根据列类型返回已分拣的集合

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];
    }    
};
决定列类型:可以是字符串、数字甚至日期

ctrl.getColumnType = () => {
    if(ctrl.sortedCol === 'firstname' || ctrl.sortedCol === 'lastname' || ctrl.sortedCol === 'cars'){
        return 'string';
    } else if(ctrl.sortedCol === 'salary' || ctrl.sortedCol === 'age'){
        return 'number';
    }
};

@SergL我刚刚提到,在angular docs示例中,JSON数据中的数字没有用引号括起来。我猜这就是我应该对我的JSON数据做的。我今天也必须做JSON数字检查。很好。我第一次使用了
JSON\u NUMERIC\u CHECK
,非常棒。JSON\u NUMERIC\u CHECK非常棒。这很有魅力,谢谢@dewd!仅供参考,JSON\u数字\u检查也可以破坏东西。它删除前导零。电话号码,0401231234变成401231234。@ FiZe我从来不认为电话号码是“号码”,它应该始终是一个字符串。我如何通过降序排序?通过降序来订购,您可以添加一个-PARSETIN():返回-(PARSETIN(人。ID));甚至更好的是,您可以向sorterFunc添加一个参数,以指定排序类型ASC或DESChow person是如何通过的here@Omar,无论您在Angular HTML中命名什么函数,在本例中为“sorterFunc”,ng repeat都会调用该函数,其参数设置为repeat实例的值。因此,由于它说:ng repeat=“PERSON in people | orderBy:sorterFunc”,当sorterFunc被称为“PERSON”的值时,在ng repeat的迭代中,被发送作为其参数。或者换句话说,“|”(pipe)字符表示获取左侧表达式的输出,并将其传递给右侧的对象。在每次迭代中,左边的输出是单个person值。
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];
    }    
};
ctrl.getColumnType = () => {
    if(ctrl.sortedCol === 'firstname' || ctrl.sortedCol === 'lastname' || ctrl.sortedCol === 'cars'){
        return 'string';
    } else if(ctrl.sortedCol === 'salary' || ctrl.sortedCol === 'age'){
        return 'number';
    }
};