Фільтруйте результати з 6 по 10 із 100 за допомогою ng-повтору в AngularJS


77

Я бачу limitToфільтр у документації, який дозволяє мені обмежити перші 5 або останні 5 результатів, але я хочу встановити, де починається мій ліміт, щоб я міг показати другий набір із 5 результатів.

Чи є для цього вбудований фільтр?

Відповіді:


147

Починаючи з 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.0limitTo :

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

2
Відповідь @ bluescreen нижче (з 20 голосами проти) - це правильна відповідь тут. Будь ласка, виберіть його.
RavenHursT

2
постійно видавав мені помилки щодо невизначеності arr, тому я зробив це arr = arr || []; return arr.slice (початок, кінець);
Джеймс Гаррінгтон,

Я не можу отримати це з ControllerAsпозначенням: jsfiddle.net/r9kvaydh/3
Simon H

1
@SimonHitem in main.items
Michelle Tilley

2
limitTo filter у angular тепер надає підтримку для визначення того, з чого починаються обмеження, {{ limitTo_expression | limitTo : limit : begin}}
Jiby Jose

133

AngularJS надає цю функціональність вже нестандартно. Якщо ви уважно прочитаєте ліміт До документації, це дозволяє вказати від’ємне значення для ліміту. Це означає N елементів в кінці, тому, якщо ви хочете обробити 5 результатів після зсуву 5, вам потрібно зробити наступне:

<div ng-repeat="item in items | limitTo: 10 | limitTo: -5">{{item}}</div>


Це рішення відповідає на питання, задане трійнику. Але будьте обережні, це працює лише для другого набору результатів. Це не буде працювати для 1-го, 3-го, 4-го набору чи будь-якого іншого. (Перший limitTo створює масив з першими 10 елементами джерела, другий limitTo тоді може працювати лише в межах цих результатів.)
Тайлер

11
Це може йти неправильно на останній сторінці. Припустимо, що є 7 пунктів, на першій сторінці показані пункти 1-5, на другій сторінці мають бути пункти 6 і 7, але тут він буде відображати пункт 3-7.
Гаррі Остервен

4
The length of the returned array or string. If the limit number is positive, limit number of items from the beginning of the source array/string are copied. If the number is negative, limit number of items from the end of the source array/string are copied. The limit will be trimmed if it exceeds array.length Я вважаю, що ця відповідь не правильна.
connorbode

@connorbode чому ні ?! Не могли б ви навести приклад?
AturSams

37

Я почав пограти з фільтрами клієнтів, але потім з'ясував, що ви можете просто зателефонувати sliceвсередині ng-repeatвиразу:

<div ng-repeat="item in items.slice(6, 10)">{{item}}</div>

2
Найпростіша відповідь. Дякую! Я думав, що другим параметром є довжина, але, мабуть, це була зупинна позиція.
AskYous

2
Це повинно бути вгорі
Судхакар,

Це найкраща відповідь, якщо ви перебуваєте на Angular 1.2.X або раніше
TWR Cole

4

Як сказав 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>

3

Ось функціональний приклад того, як фільтрувати список зі зміщенням та обмеженням:

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

Зверніть увагу, що фільтр для зміщення повинен бути встановлений як перший фільтр, якщо ви хочете охопити загальний випадок, коли межа невідома.


2

з відповіді на блюз екрані:

<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 елементів


1

Існує більш акуратний спосіб зробити це без необхідності викликати фільтр і буде поводитися більше як пагінатор:

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

1

Ви також можете створити свій власний багаторазовий фільтр startFrom приблизно так:

myApp.filter('startFrom', function () {
    return function (input, start) {
        start = +start;
        return input.slice(start);
    }
});

а потім використовуйте його у своєму ng-повторенні приблизно так:

ng-repeat="item in items | startFrom: 5 | limitTo:5

Таким чином, це робиться "в дусі фільтрів AngularJs", перевіряється, може мати певну "додаткову" логіку, якщо потрібно, і т.д.


0

Анси @ bluescreen і анси @ Brandon не є рівнозначними.

наприклад:

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]


0

Для іонних проектів знайдіть рішення нижче:

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
  }

});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.