Ograniczenie liczby wyświetlanych wyników podczas korzystania z ngRepeat

148

Uważam, że tutoriale AngularJS są trudne do zrozumienia; ten prowadzi mnie przez proces tworzenia aplikacji wyświetlającej telefony. Jestem na etapie 5 i pomyślałem, że w ramach eksperymentu spróbuję pozwolić użytkownikom określić, ilu chcieliby, aby ich wyświetlono. Widok wygląda następująco:

<body ng-controller="PhoneListCtrl">

  <div class="container-fluid">
    <div class="row-fluid">
      <div class="span2">
        <!--Sidebar content-->

        Search: <input ng-model="query">
        How Many: <input ng-model="quantity">
        Sort by:
        <select ng-model="orderProp">
          <option value="name">Alphabetical</option>
          <option value="age">Newest</option>
        </select>

      </div>
      <div class="span10">
        <!--Body content-->

        <ul class="phones">
          <li ng-repeat="phone in phones | filter:query | orderBy:orderProp">
            {{phone.name}}
            <p>{{phone.snippet}}</p>
          </li>
        </ul>

      </div>
    </div>
  </div>
</body>

Dodałem tę linię, w której użytkownicy mogą wpisać, ile wyników chcą pokazać:

How Many: <input ng-model="quantity">

Oto mój kontroler:

function PhoneListCtrl($scope, $http) {
  $http.get('phones/phones.json').success(function(data) {
    $scope.phones = data.splice(0, 'quantity');
  });

  $scope.orderProp = 'age';
  $scope.quantity = 5;
}

Ważną linią jest:

$scope.phones = data.splice(0, 'quantity');

Potrafię na stałe zakodować liczbę, aby określić, ile telefonów powinno być wyświetlanych. Jeśli wstawię 5, pokaże się 5. Chcę tylko odczytać liczbę w tym wejściu z widoku i umieścić ją w data.splicewierszu. Próbowałem z cytatami i bez nich, ale żadne z nich nie działa. Jak mam to zrobic?

Kapitan Stack
źródło

Odpowiedzi:

345

Nieco bardziej „kątowym sposobem” byłoby użycie prostego limitTofiltru, który natywnie zapewnia Angular:

<ul class="phones">
  <li ng-repeat="phone in phones | filter:query | orderBy:orderProp | limitTo:quantity">
    {{phone.name}}
    <p>{{phone.snippet}}</p>
  </li>
</ul>
app.controller('PhoneListCtrl', function($scope, $http) {
    $http.get('phones.json').then(
      function(phones){
        $scope.phones = phones.data;
      }
    );
    $scope.orderProp = 'age';
    $scope.quantity = 5;
  }
);

PLUNKER

Stewie
źródło
54
Warto zwrócić uwagę - i zaoszczędzić komuś kilka minut - że jeśli używasz „track by” MUSI być ostatni po filtrach.
stephan.com,
3
Czy istnieje sposób, aby uzyskać liczbę dostępnych pozycji, używając filtrów i limitTo? Chciałbym użyć limitToprzycisku „wczytaj więcej”, aby zwiększyć limit. Powinien być wyświetlany tylko wtedy, gdy dostępnych jest więcej rekordów.
Tim Büthe
Co to jest filter:query?
bigpony
@defmx na pytanie OP, querypochodzi zSearch: <input ng-model="query">
jusopi
45

Trochę za późno na imprezę, ale to zadziałało. Mam nadzieję, że ktoś inny uzna to za przydatne.

<div ng-repeat="video in videos" ng-if="$index < 3">
    ...
</div>
couzzi
źródło
2
Podejrzewam, że byłoby to mniej wydajne niż użycie limitToFilter, jeśli jest to duża tablica, ponieważ każdy element prawdopodobnie musi zostać oceniony
rom99
3
Miałem scenariusz, w którym chciałem pokazać 6 elementów z dużo większej liczby kopii. Użycie ng-if="$index < 6"pozwoliło mi pokazać tylko pierwsze 6, zachowując możliwość przeszukiwania całej tablicy (mam filtr połączony z polem wyszukiwania).
Jeroen Vannevel
To nie jest limit, to ukrywanie całego wyniku, jeśli
policzysz
@ Jek-fdrv - Nie, ng-ifw tym przypadku nie wyrenderuje elementu DOM repeatera, którego wartość $indexjest większa niż 3. jeśli $indexw repeaterze jest 0, 1, or 2, warunek jest truei tworzone są węzły DOM. ng-ifróżni się od ng-hidetego, że elementy nie są dodawane do DOM.
couzzi
2

początkowo przechowywać wszystkie dane

function PhoneListCtrl($scope, $http) {
  $http.get('phones/phones.json').success(function(data) {
    $scope.phones = data.splice(0, 5);
    $scope.allPhones = data;
  });

  $scope.orderProp = 'age';
  $scope.howMany = 5;
  //then here watch the howMany variable on the scope and update the phones array accordingly
  $scope.$watch("howMany", function(newValue, oldValue){
    $scope.phones = $scope.allPhones.splice(0,newValue)
  });
}

EDIT przypadkowo umieścił zegarek poza kontrolerem, w którym powinien się znajdować.

shaunhusain
źródło
2

tutaj jest inny sposób na ograniczenie filtra do html, na przykład chcę wyświetlić 3 listy na raz niż użyję limitTo: 3

  <li ng-repeat="phone in phones | limitTo:3">
    <p>Phone Name: {{phone.name}}</p>
  </li>
Rizo
źródło
1

Działa to lepiej w moim przypadku, jeśli masz obiekt lub tablicę wielowymiarową. Pokaże tylko pierwsze elementy, inne będą po prostu ignorowane w pętli.

.filter('limitItems', function () {
  return function (items) {
    var result = {}, i = 1;
    angular.forEach(items, function(value, key) {
      if (i < 5) {
        result[key] = value;
      }
      i = i + 1;
    });
    return result;
  };
});

Zmień 5 na to, co chcesz.

fdrv
źródło
0

Użyj filtra limitTo, aby wyświetlić ograniczoną liczbę wyników w ng-repeat.

<ul class="phones">
      <li ng-repeat="phone in phones | limitTo:5">
        {{phone.name}}
        <p>{{phone.snippet}}</p>
      </li>
</ul>
Rajkiran Shetty
źródło
-3

Innym (i myślę, że lepszym) sposobem osiągnięcia tego jest faktyczne przechwycenie danych. LimitTo jest w porządku, ale co, jeśli ograniczasz do 10, gdy twoja tablica faktycznie zawiera tysiące?

Dzwoniąc do mojego serwisu, po prostu zrobiłem to:

TaskService.getTasks(function(data){
    $scope.tasks = data.slice(0,10);
});

Ogranicza to to, co jest wysyłane do widoku, więc powinno być znacznie lepsze dla wydajności niż robienie tego na froncie.

Matt Saunders
źródło
Implementacja limitTo i tak używa array.slice (), każda różnica w rozmiarze tablicy powinna mieć taką samą różnicę w wydajności, jak zrobienie tego samodzielnie. github.com/angular/angular.js/blob/master/src/ng/filter/…
rom99
ale limitTo w rzeczywistości nie ogranicza danych wysyłanych do widoku, podczas gdy robi to w ten sposób. Przetestowałem to za pomocą console.log ().
Matt Saunders,
1
Tak, to, co robisz, to wystawianie nowej tablicy na widok (tak naprawdę nie myślałbym o tym jako o „wysyłaniu” czegokolwiek). Jeśli interesowało Cię tylko pierwszych 10 elementów danych, a do danych nie ma odniesień nigdzie indziej, zrobienie tego w ten sposób może zmniejszyć zużycie pamięci (zakładając, że dane mogą być zbierane jako śmieci). Ale jeśli nadal masz odniesienie do dataaround, nie jest to bardziej wydajne niż użycie limitTo.
rom99