Я вижу фильтр limitTo
в документах, что позволяет мне ограничить первые 5 или последние 5 результатов, но я хочу установить, где мой предел начинается, поэтому я могу показать второй набор из 5 результатов.
Есть ли встроенный фильтр для этого?
Я вижу фильтр limitTo
в документах, что позволяет мне ограничить первые 5 или последние 5 результатов, но я хочу установить, где мой предел начинается, поэтому я могу показать второй набор из 5 результатов.
Есть ли встроенный фильтр для этого?
Так как Angular 1.4.0, limitTo
фильтр принимает необязательный аргумент begin
:
<div ng-repeat="item in items | limitTo:5:5">{{item}}</div>
В старых версиях запись пользовательского фильтра довольно проста. Здесь наивная реализация, основанная на Array#slice
(обратите внимание, что вы передаете первый и последний индекс, а не счет):
app.filter('slice', function() {
return function(arr, start, end) {
return (arr || []).slice(start, end);
};
});
<div ng-repeat="item in items | slice:6:10">{{item}}</div>
Работа jsFiddle: http://jsfiddle.net/BinaryMuse/vQUsS/
В качестве альтернативы вы можете просто украсть всю реализацию Angular 1.4.0 limitTo
:
function limitToFilter() {
return function(input, limit, begin) {
if (Math.abs(Number(limit)) === Infinity) {
limit = Number(limit);
} else {
limit = toInt(limit);
}
if (isNaN(limit)) return input;
if (isNumber(input)) input = input.toString();
if (!isArray(input) && !isString(input)) return input;
begin = (!begin || isNaN(begin)) ? 0 : toInt(begin);
begin = (begin < 0 && begin >= -input.length) ? input.length + begin : begin;
if (limit >= 0) {
return input.slice(begin, begin + limit);
} else {
if (begin === 0) {
return input.slice(limit, input.length);
} else {
return input.slice(Math.max(0, begin + limit), begin);
}
}
};
}
AngularJS предоставляет эту функциональность уже из коробки. Если вы внимательно прочитаете документацию limitTo, вы можете указать отрицательное значение для лимита. Это означает, что N элементов в конце, поэтому, если вы хотите обработать 5 результатов после смещения 5, вам необходимо сделать следующее:
<div ng-repeat="item in items | limitTo: 10 | limitTo: -5">{{item}}</div>
Я начал играть с фильтрами клиентов, но потом выяснил, что вы можете просто вызвать slice
внутри выражения ng-repeat
:
<div ng-repeat="item in items.slice(6, 10)">{{item}}</div>
Как сказал bluescreen, это можно сделать, используя только фильтр limitTo
, хотя проблема с последней страницей, которую заметил Гарри Оустрийн, нуждается в дополнительной работе.
т.е. используя свойства ui-bootstrap pagination
:
ng-model = page // current page
items-per-page = rpp // records per page
total-items = count // total number of records
Выражение должно быть:
<div ng-repeat="item in items | limitTo: rpp * page | limitTo: rpp * page < count ? -rpp : rpp - (rpp * page - count)">{{item}}</div>
Здесь приведен пример использования фильтра для смещения и ограничения:
<!doctype html>
<html lang="en" ng-app="phonecatApp">
<head>
<script src="lib/angular/angular.js"></script>
<script src="js/controllers.js"></script>
</head>
<body ng-controller="PhoneListCtrl">
Offset: <input type="text" ng-model="offset" value="0" /><br />
Limit: <input type="text" ng-model="limit" value="10" /><br />
<p>offset limitTo: {{offset - phones.length}}</p>
<p>Partial list:</p>
<ul>
<li ng-repeat="phone in phones | limitTo: offset - phones.length | limitTo: limit">
{{$index}} - {{phone.name}} - {{phone.snippet}}
</li>
</ul>
<hr>
<p>Whole list:</p>
<ul>
<li ng-repeat="phone in phones">
{{$index}} - {{phone.name}} - {{phone.snippet}}
</li>
</ul>
</body>
</html>
Пример основан на втором этапе учебника AngularJS.
Обратите внимание, что фильтр для смещения должен быть помещен как первый фильтр, если вы хотите покрыть общий случай, когда предел uknnown.
из ответа bluescreen:
<div ng-repeat="item in items | limitTo: 10 | limitTo: -5">{{item}}</div>
вы также можете найти сценарий, в котором вам нужно взять N-й элемент до последнего элемента, это еще один способ использования limitTo:
<div ng-repeat="item in items | limitTo:-(items.length-5)>{{item}}</div>
отрицательный знак займет столько же, сколько и items.length от последнего, то минус 5 внутри скобки пропустит первые 5 элементов
Там более аккуратный способ сделать это без необходимости ссылаться на фильтр и будет вести себя скорее как paginator:
$scope.page = 0;
$scope.items = [ "a", "b", "c", "d", "e", "f", "g" ];
$scope.itemsLimit = 5;
$scope.itemsPaginated = function () {
var currentPageIndex = $scope.page * $scope.itemsLimit;
return $scope.items.slice(
currentPageIndex,
currentPageIndex + $scope.itemsLimit);
};
И просто придерживайтесь этого, на ваш взгляд:
<ul>
<li ng-repeat="item in itemsPaginated() | limitTo:itemsLimit">{{item}}</li>
</ul>
Затем вы можете просто увеличить/уменьшить $scope.page
:
$scope.page++;
@bluescreen ans и @Brandon ans не эквивалентны.
например:
var pageSize = 3;
var page = 2;
var items = [1, 2, 3, 4];
-
item in items | limitTo: page*pageSize | limitTo: -1*pageSize
производят [2, 3, 4]
item in items | slice: (page-1)*pageSize : page*pageSize
производят [4]
Вы также можете создать свой собственный многоразовый фильтр startFrom следующим образом:
myApp.filter('startFrom', function () {
return function (input, start) {
start = +start;
return input.slice(start);
}
});
а затем используйте его в своем ng-repeat так:
ng-repeat="item in items | startFrom: 5 | limitTo:5
Таким образом, это делается "в духе фильтров AngularJs", проверяемый, может иметь некоторую "дополнительную" логику при необходимости и т.д.
Для проектов, основанных на ионах, найти решение ниже:
mainpage.html:
<ion-view view-title="My Music">
<ion-content>
<ion-list>
<ion-item ng-repeat="track in tracks | limitTo: limit | limitTo: -10 ">
{{track.title}}
</ion-item>
</ion-list>
<div class="list"></div>
<div align="center">
<button class="button button-small button-positive" ng-disabled="currentPage == 0" ng-click="decrementLimit()">
Back
</button>
<button class="button button-small button-energized">
{{currentPage+1}}/{{numberOfPages()}}
</button>
<button class="button button-small button-positive" ng-disabled="currentPage >= data_length/pageSize - 1" ng-click="incrementLimit()">
Next
</button>
</div>
</ion-content>
</ion-view>
controller.js:
var myApp = angular.module('musicApp.controllers', []);
myApp.controller('AppCtrl', function($scope, $http) {
console.log('AppCtrl called');
// $scope.tracks = MusicService.query();
$http.get('api/to/be/called').then(function(result){
$scope.tracks = result.data['results'];
$scope.data_length = $scope.tracks.length;
console.log(result)
// console.log($sco pe.tracks.length)
});
var currentPage = 0;
$scope.pageSize = 10;
$scope.numberOfPages = function(){
return Math.ceil($scope.tracks.length/$scope.pageSize);
}
var limitStep = 10;
$scope.limit = limitStep;
$scope.currentPage = currentPage;
$scope.incrementLimit = function(){
$scope.limit += limitStep;
$scope.currentPage += 1
};
$scope.decrementLimit = function(){
$scope.limit -= limitStep;
$scope.currentPage -= 1
}
});