Filtern Sie die Ergebnisse 6 bis 10 von 100 mit ng-repeat in AngularJS

77

Ich sehe den limitToFilter in den Dokumenten, mit dem ich die ersten 5 oder letzten 5 Ergebnisse begrenzen kann, aber ich möchte festlegen, wo mein Limit beginnt, damit ich den zweiten Satz von 5 Ergebnissen anzeigen kann.

Gibt es dafür einen eingebauten Filter?

Coder1
quelle

Antworten:

147

Seit Angular 1.4.0 verwendet der limitToFilter ein optionales beginArgument:

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

In älteren Versionen ist das Schreiben eines benutzerdefinierten Filters ziemlich einfach. Hier ist eine naive Implementierung basierend auf Array#slice(beachten Sie, dass Sie den ersten und den letzten Index anstelle einer Zählung übergeben):

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>

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

Alternativ können Sie einfach die gesamte Angular 1.4.0-ImplementierunglimitTo stehlen von :

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);
      }
    }
  };
}
Michelle Tilley
quelle
2
Die Antwort von @ bluescreen unten (mit 20 Stimmen) ist hier die richtige Antwort. Bitte wählen Sie diesen aus.
RavenHursT
2
gab mir immer wieder Fehler, dass arr undefiniert war, also tat ich dies arr = arr || []; return arr.slice (Start, Ende);
James Harrington
Ich kann das nicht mit ControllerAsNotation erreichen: jsfiddle.net/r9kvaydh/3
Simon H
1
@ SimonHitem in main.items
Michelle Tilley
2
limitTo Filter in Angular bietet jetzt Unterstützung, um zu definieren, wo Limits ebenfalls beginnen {{ limitTo_expression | limitTo : limit : begin}}
Jiby Jose
133

AngularJS bietet diese Funktionalität bereits ab Werk. Wenn Sie die limitTo-Dokumentation sorgfältig lesen, können Sie einen negativen Wert für das Limit angeben. Das bedeutet N Elemente am Ende. Wenn Sie also 5 Ergebnisse nach einem Versatz von 5 verarbeiten möchten, müssen Sie Folgendes tun:

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

blauer Bildschirm
quelle
Diese Lösung beantwortet die Frage, die einem Abschlag gestellt wird. Aber Vorsicht, dies funktioniert nur für den 2. Satz von Ergebnissen. Es funktioniert nicht für den 1., 3., 4. Satz oder andere. (Das erste limitTo erstellt ein Array mit den ersten 10 Elementen der Quelle, das zweite limitTo kann dann nur innerhalb dieser Ergebnisse arbeiten.)
Tyler
11
Dies geht möglicherweise auf der letzten Seite schief. Angenommen, es gibt 7 Elemente, auf der ersten Seite werden die Elemente 1-5 angezeigt, auf der zweiten Seite sollten die Elemente 6 und 7 angezeigt werden, hier werden jedoch die Elemente 3-7 angezeigt.
Harry Oosterveen
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 Ich denke nicht, dass diese Antwort richtig ist.
Connorbode
@connorbode warum nicht?! Könnten Sie ein Beispiel geben?
AturSams
37

Ich habe angefangen, mit Kundenfiltern herumzuspielen, aber dann herausgefunden, dass Sie einfach sliceinnerhalb des ng-repeatAusdrucks aufrufen können :

<div ng-repeat="item in items.slice(6, 10)">{{item}}</div>
tjwallace
quelle
2
Einfachste Antwort. Vielen Dank! Ich dachte, der zweite Parameter sei die Länge, aber anscheinend die Halteposition.
AskYous
2
Dies sollte oben sein
Sudhakar
Dies ist die beste Antwort, wenn Sie auf Angular 1.2.X oder früher sind
TWR Cole
4

Wie Bluescreen sagte, kann dies nur mit dem limitToFilter durchgeführt werden, obwohl die Behandlung des von Harry Oosterveen festgestellten Problems der letzten Seite zusätzliche Arbeit erfordert.

Dh mit den Eigenschaften der UI-Bootstrap- pagination Direktive:

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

Der Ausdruck sollte sein:

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

Hier ist ein Funktionsbeispiel zum Filtern einer Liste mit Offset und 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>

Das Beispiel basiert auf dem zweiten Schritt des AngularJS-Tutorials .

Beachten Sie, dass der Filter für den Offset als erster Filter verwendet werden muss, wenn Sie den allgemeinen Fall abdecken möchten, in dem der Grenzwert unbekannt ist.

xmak
quelle
2

von Bluescreen Antwort:

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

Möglicherweise finden Sie auch ein Szenario, in dem Sie den N-ten Gegenstand bis zum letzten Gegenstand nehmen müssen. Dies ist eine andere Möglichkeit, limitTo zu verwenden:

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

Das negative Vorzeichen nimmt so viel wie items.length vom letzten an, dann überspringen minus 5 in der Klammer die ersten 5 Elemente

Mithocondrien
quelle
1

Es gibt einen übersichtlicheren Weg, dies zu tun, ohne einen Filter aufrufen zu müssen, und der sich eher wie ein Paginator verhält:

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

Und halten Sie das einfach in Ihrer Sicht:

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

Dann können Sie einfach inkrementieren / dekrementieren $scope.page:

$scope.page++;
marksyzm
quelle
1

Sie können auch Ihren eigenen wiederverwendbaren Filter startFrom wie folgt erstellen:

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

und dann benutze es in deiner ng-Wiederholung wie folgt:

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

Auf diese Weise wird es "im Geiste von AngularJs Filtern" durchgeführt, testbar, kann bei Bedarf eine "zusätzliche" Logik haben usw.

Schürze
quelle
0

@ bluescreen's ans und @ Brandon's ans sind nicht gleichwertig.

zum Beispiel:

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

- -

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

produzieren [2, 3, 4]

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

produzieren [4]

CaryLorrk
quelle
0

Für ionische Projekte finden Sie die folgende Lösung:

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
  }

});
RakeshKB
quelle