Ordenação angularDe ordenação numérica como texto em ng-repeat

Eu tenho esses dados:

[{"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"}] 

Quando eu orderBy id ou por idade em um ng-repeat, ele classifica o número como texto. Como não consigo encontrá-lo escrito que isso é um problema em qualquer lugar, estou supondo que há um problema com meu código. Eu criei este violino: http://jsfiddle.net/vsbGH/1/ Desculpe pelo modelo, mas jsfiddle não permite na checkbox de html. De qualquer forma, este é o código que carrega e classifica os dados:

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

E esta é a parte de repetição do ng:

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

Muito obrigado se você puder me ajudar a entender por que os dados numéricos não estão sendo classificados como números e por que eles estão sendo classificados como texto.

Acho que a solução mais apropriada é formatar corretamente os números que tenho em meus objects JSON, ou seja, não envolvê-los entre aspas. Assim:

  [{"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"}] 

torna-se:

 [{"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"}] 

Eu estou supondo que a solução do SergL é boa se não for possível corrigir o formato dos dados JSON.

Para adicionar isso, o problema no meu caso específico é fazer com a function json_encode do PHP no lado do servidor. Por padrão, ele trata números como strings. Para corrigir, tive que adicionar a opção JSON_NUMERIC_CHECK ao método de codificação no script PHP:

 json_encode($assoc_array,JSON_NUMERIC_CHECK); 

Você não precisa modificar seu JSON. Você pode passar uma function para orderBy filter assim:

 $scope.sorterFunc = function(person){ return parseInt(person.id); };  {{person.id | number}} {{person.firstname}}  {{person.lastname}}  {{person.age | number}} {{person.cars}}   

Dentro da sua diretiva ng-repeat você está usando um filtro numérico

 {{person.id | number}} 

Os filtros são usados ​​para formatar a saída, mas não atualizam as propriedades do modelo. Por exemplo: person.id = 1234.56789 será processado como 1.234.568.

Como mencionado acima, você deve converter a idade para digitar Number. Então orderBy funcionará como deveria. Por exemplo, dentro do seu serviço:

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

Se o seu valor orderBy não for uma variável apontando para outra string, mas sim o atributo pelo qual você estará classificando, você deverá colocá-lo entre aspas.

 person in people | orderBy:'-id' 

Se, depois de você ter analisado seu int ou float e ainda não estiver classificando corretamente, pode ser por causa disso. <: / (essa é minha capa de burro)

Eu enfrentei o mesmo problema quando eu estava trabalhando com um campo de texto e ngModel para alterar o valor do modelo que eu estava pedindo. Porque o valor foi considerado como string.

Com o novo HTML5 , Angular analisa o valor do campo de input para um número (float acho), o que me ajudou a obter a ordem correta.

Deixe orderBy apontar para um método pertencente ao escopo ou seus ancestrais não isolados e deixe esse método retornar um número lançado da string. Você pode ter que escrever uma diretiva herdando o escopo de person criado pelas instâncias ngRepeat para adicionar esse método.

Além disso, no seu caso, a idade é uma cadeia onde poderia ter sido um número inteiro e, portanto, a sorting numérica seria aplicada nativamente.

Se você não puder alterar os servidores de dados, altere-o ao fazer uma busca.

É melhor atualizar sua coleção repetida sempre que uma function de sorting for chamada. Aqui estou usando Lodash – orderBy apenas para solicitar a coleção com base em uma function classificadora. Vamos dizer que o tipo é chamado no clique do header da coluna da tabela.

Exemplo:

Objeto de coleção:

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

O usuário clica no header da coluna para classificar por idade:

 Age 

Método chamado:

 ctrl.sortColumn('age'); // where age is column containing numbers only 

Implementação do método:

 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 

Função de sorting: retorna a coleção classificada com base no tipo de coluna

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

Decidir tipo de coluna: pode ser string, número ou até mesmo data

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