Filter results 6 through 10 of 100 with ng-repeat in AngularJS

Angularjs

Angularjs Problem Overview


I see the limitTo filter in the docs, which allows me to limit the first 5, or last 5 results, but I want to set where my limit starts so I can show the second set of 5 results.

Is there a built in filter for that?

Angularjs Solutions


Solution 1 - Angularjs

Since Angular 1.4.0, the limitTo filter takes an optional begin argument:

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

In older versions, writing a custom filter is fairly straightforward. Here's a naïve implementation based on Array#slice (note you pass the first and last index, instead of a count):

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>

Working jsFiddle: http://jsfiddle.net/BinaryMuse/vQUsS/

Alternatively, you can simply steal the entire Angular 1.4.0 implementation of 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);
      }
    }
  };
}

Solution 2 - Angularjs

AngularJS provides that functionality already out of the box. If you carefully read the limitTo documentation it allows you to specify a negative value for the limit. That means N elements at the end so if you want to process 5 results after an offset of 5 you need to do the following:

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

Solution 3 - Angularjs

I started playing around with customer filters but then found out you can just call slice inside of the ng-repeat expression:

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

Solution 4 - Angularjs

As bluescreen said, it can be done using only the limitTo filter, although dealing with the last page problem noticed by Harry Oosterveen needs some extra work.

I.e. using ui-bootstrap pagination directive properties:

ng-model       = page  // current page
items-per-page = rpp   // records per page
total-items    = count // total number of records

The expression should be:

<div ng-repeat="item in items | limitTo: rpp * page | limitTo: rpp * page < count ? -rpp : rpp - (rpp * page - count)">{{item}}</div>

Solution 5 - Angularjs

Here's a functional example on how to filter a list with offset and limit:

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

The example is based on the second step of AngularJS tutorial.

Note that the filter for the offset has to be put as the first filter if you want to cover the generic case where the limit is uknnown.

Solution 6 - Angularjs

from bluescreen answer :

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

you might also find a scenario where you need to take N-th item till the last item, this is another way using limitTo:

<div ng-repeat="item in items | limitTo:-(items.length-5)>{{item}}</div>

negative sign will take as much as items.length from last, then minus 5 inside the bracket will skip the first 5 items

Solution 7 - Angularjs

There's a tidier way to do it without having to invoke a filter and will behave more like a 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);
};

And just stick that in your view:

<ul>
    <li ng-repeat="item in itemsPaginated() | limitTo:itemsLimit">{{item}}</li>
</ul>

Then you can just increment/decrement $scope.page:

$scope.page++;

Solution 8 - Angularjs

You can also create your own reusable filter startFrom like so:

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

and then use it in your ng-repeat like so:

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

That way it is done "in a spirit of AngularJs filters", testable, can have some "extra" logic if needed, etc.

Solution 9 - Angularjs

@bluescreen's ans and @Brandon's ans are not equivalent.

for example:

var pageSize = 3;  
var page = 2;
var items = [1, 2, 3, 4];  

--

item in items | limitTo: page*pageSize | limitTo: -1*pageSize  

produce [2, 3, 4]

item in items | slice: (page-1)*pageSize : page*pageSize  

produce [4]

Solution 10 - Angularjs

For Ionic based projects find the solution below:

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
  }

});

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCoder1View Question on Stackoverflow
Solution 1 - AngularjsMichelle TilleyView Answer on Stackoverflow
Solution 2 - AngularjsbluescreenView Answer on Stackoverflow
Solution 3 - AngularjstjwallaceView Answer on Stackoverflow
Solution 4 - AngularjsIgdtlView Answer on Stackoverflow
Solution 5 - AngularjsxmakView Answer on Stackoverflow
Solution 6 - AngularjsmithocondriaView Answer on Stackoverflow
Solution 7 - AngularjsmarksyzmView Answer on Stackoverflow
Solution 8 - AngularjsPinnyView Answer on Stackoverflow
Solution 9 - AngularjsCaryLorrkView Answer on Stackoverflow
Solution 10 - AngularjsRakeshKBView Answer on Stackoverflow