Почему не работает угловой заказ по заказному компаратору?
Я пытаюсь реализовать пользовательский компаратор для угловой директивы orderBy. Как видно из фрагмента кода, пользовательский компаратор игнорируется (ничего не записывается в console.log), даже если он должен работать в соответствии с угловой документацией для orderBy.
angular.module('orderByExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.files = [
{name: 'File1', size: '1.2 Mb'},
{name: 'File2', size: '2.4 Kb'},
{name: 'File3', size: '241 Bytes'},
{name: 'File4', size: '2.0 Mb'},
{name: 'File5', size: '16.1 Kb'}
];
$scope.fileSizeComparator = function(s1, s2) {
// split the size string in nummeric and alphabetic parts
console.log(s1);
console.log(s2);
var s1Splitted = s1.size.split(" ");
var s2Splitted = s2.size.split(" ");
if (s1Splitted[1] === s2Splitted[1]) {
// if size type is the same, compare the number
return s1Splitted[0] > s2Splitted[0];
}
// default : compare on size type Mb > Kb > Bytes
return s1Splitted[1] > s2Splitted[1];
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="orderByExample">
<div ng-controller="ExampleController">
<table>
<tr>
<th>Name</th>
<th>Size</th>
</tr>
<tr ng-repeat="file in files | orderBy:'size':false:fileSizeComparator">
<td>{{file.name}}</td>
<td>{{file.size}}</td>
</tr>
</table>
</div>
</div>
Я протестировал пример кода из угловой документации на JsFiddle, и он тоже не работает. Есть идеи?
3 ответа
Я нашел решение после некоторой помощи от @morels: да, я действительно должен вернуть 1 и -1. Но главная проблема заключалась в том, что компаратор игнорировался. По-видимому, это потому, что эта функция доступна только для угловых 1.5.7 и выше. Мне также нужно было использовать .split
на .value
из переданных параметров s1 и s2.
Вот рабочее решение в фрагменте кода:
angular.module('orderByExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.files = [
{name: 'File1', size: '1.2 Mb'},
{name: 'File2', size: '2.4 Kb'},
{name: 'File3', size: '241 Bytes'},
{name: 'File4', size: '2.0 Mb'},
{name: 'File5', size: '16.1 Kb'}
];
$scope.fileSizeComparator = function(s1, s2) {
// split the size string in nummeric and alphabetic parts
var s1Splitted = s1.value.split(" ");
var s2Splitted = s2.value.split(" ");
if (s1Splitted[1] === s2Splitted[1]) {
// if size type is the same, compare the number
return parseFloat(s1Splitted[0]) > parseFloat(s2Splitted[0]) ? -1 : 1;
}
// default : compare on size type Mb > Kb > Bytes
return s1Splitted[1] > s2Splitted[1] ? -1 : 1;
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<div ng-app="orderByExample">
<div ng-controller="ExampleController">
<table>
<tr>
<th>Name</th>
<th>Size</th>
</tr>
<tr ng-repeat="file in files | orderBy:'size':false:fileSizeComparator">
<td>{{file.name}}</td>
<td>{{file.size}}</td>
</tr>
</table>
</div>
</div>
Потому что вы должны вернуться -1,0,1
не true,false
,
После официальной документации вы можете увидеть формат типичной функции сравнения:
$scope.localeSensitiveComparator = function(v1, v2) { // If we don't get strings, just compare by index if (v1.type !== 'string' || v2.type !== 'string') { return (v1.index < v2.index) ? -1 : 1; } // Compare strings alphabetically, taking locale into account return v1.value.localeCompare(v2.value); };
Пожалуйста, переписать как:
$scope.fileSizeComparator = function(s1, s2) {
// split the size string in nummeric and alphabetic parts
console.log(s1);
console.log(s2);
var s1Splitted = s1.size.split(" ");
var s2Splitted = s2.size.split(" ");
if (s1Splitted[1] === s2Splitted[1]) {
// if size type is the same, compare the number
if ( s1Splitted[0] > s2Splitted[0])
return 1;
else
return -1;
}
// default : compare on size type Mb > Kb > Bytes
return s1Splitted[1] > s2Splitted[1] ? -1 : 1;
};
Обратите внимание, что вы никогда не пропустите равенство, т.е. 0
,
Делай так
ng-repeat="file in files | orderBy: sizeFilter: true"
$scope.sizeFilter=function(file){
$scope.size = file.size;
return $scope.size;
};