Limitazione del numero di risultati visualizzati quando si utilizza ngRepeat


148

Trovo i tutorial di AngularJS difficili da capire; questo mi sta guidando attraverso la creazione di un'app che visualizza i telefoni. Sono al passaggio 5 e ho pensato che, come esperimento, avrei cercato di consentire agli utenti di specificare quanti vorrebbero essere mostrati. La vista è simile alla seguente:

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

Ho aggiunto questa riga in cui gli utenti possono inserire il numero di risultati che vogliono mostrare:

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

Ecco il mio controller:

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

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

La linea importante è:

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

Posso codificare un numero per rappresentare quanti telefoni dovrebbero essere mostrati. Se inserisco 5, verrà mostrato 5. Tutto quello che voglio fare è leggere il numero in quell'input dalla vista e metterlo in data.spliceriga. Ho provato con e senza virgolette e nessuno dei due ha funzionato. Come faccio a fare questo?

Risposte:


345

Un po 'più "modo angolare" sarebbe usare il limitTofiltro semplice , come fornito nativamente da 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


54
Vale la pena sottolineare - e salvare qualcun altro per qualche minuto - che se stai usando "track by" DEVE essere l'ultimo dopo i filtri.
stephan.com,

3
C'è un modo per ottenere il numero di articoli disponibili quando si utilizzano il filtro e il limite? Vorrei utilizzare limitToma fornire un pulsante "carica altro" per aumentare il limite. Questo dovrebbe essere visualizzato solo se sono disponibili più record.
Tim Büthe

Che cosa è filter:query?
bigpony,

@defmx per la domanda del PO, queryviene daSearch: <input ng-model="query">
jusopi il

45

Un po 'tardi alla festa, ma questo ha funzionato per me. Eventualmente qualcun altro lo trova utile.

<div ng-repeat="video in videos" ng-if="$index < 3">
    ...
</div>

2
Sospetto che questo sarebbe meno efficiente dell'uso di limitToFilter se si tratta di un array di grandi dimensioni, perché presumibilmente ogni articolo deve essere valutato
rom99

3
Ho avuto uno scenario in cui volevo mostrare 6 elementi da un array di supporto di molto altro. L'utilizzo ng-if="$index < 6"mi ha permesso di mostrare solo i primi 6, mantenendo l'intero array ricercabile (ho un filtro combinato con un campo di ricerca).
Jeroen Vannevel,

Non è un limite, è nascondere l'intero risultato se conta più di 3.
fdrv

@ Jek-fdrv - No, ng-ifin questo caso non renderà l'elemento DOM del ripetitore il cui valore $indexè maggiore di 3. se $indexnel ripetitore è 0, 1, or 2, la condizione è truee vengono creati i nodi DOM. ng-ifdifferisce da ng-hidenel senso che gli elementi non vengono aggiunti al DOM.
couzzi

2

archivia inizialmente tutti i tuoi dati

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 aveva accidentalmente messo l'orologio fuori dal controller in cui avrebbe dovuto trovarsi all'interno.


2

ecco un altro modo per limitare il filtro su html, ad esempio voglio visualizzare 3 elenchi alla volta di quanto userò limitTo: 3

  <li ng-repeat="phone in phones | limitTo:3">
    <p>Phone Name: {{phone.name}}</p>
  </li>

1

Funziona meglio nel mio caso se hai un oggetto o un array multidimensionale. Mostrerà solo i primi elementi, gli altri verranno semplicemente ignorati in loop.

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

Cambia 5 su quello che vuoi.


0

Utilizzare limitTo filter per visualizzare un numero limitato di risultati in ng-repeat.

<ul class="phones">
      <li ng-repeat="phone in phones | limitTo:5">
        {{phone.name}}
        <p>{{phone.snippet}}</p>
      </li>
</ul>

-3

Un altro (e penso meglio) modo per raggiungere questo obiettivo è effettivamente intercettare i dati. limitTo va bene, ma cosa succede se si sta limitando a 10 quando l'array contiene effettivamente migliaia?

Quando ho chiamato il mio servizio ho semplicemente fatto questo:

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

Questo limita ciò che viene inviato alla vista, quindi dovrebbe essere molto meglio per le prestazioni rispetto a farlo sul front-end.


L'implementazione di limitTo utilizza array.slice () in ogni caso, qualsiasi differenza nelle dimensioni dell'array dovrebbe avere la stessa differenza nelle prestazioni di farlo da soli. github.com/angular/angular.js/blob/master/src/ng/filter/…
rom99

ma limitTo non limita effettivamente i dati inviati alla vista, mentre farlo in questo modo lo fa. Ho provato questo usando console.log ().
Matt Saunders,

1
Sì, quello che stai facendo è esporre un nuovo array alla vista (non lo penserei davvero come 'invio' di nulla da nessuna parte). Se ti interessano solo i primi 10 elementi dei dati e i dati non fanno riferimento in nessun altro luogo, farlo in questo modo potrebbe ridurre il footprint di memoria (supponendo che i dati possano essere raccolti in modo inutile). Ma se stai ancora mantenendo un riferimento a dataaround, questo non è più efficiente dell'uso di limitTo.
rom99,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.