2015-11-17 38 views
6

Utilizzo la direttiva md-virtual-repeat di Angular Material per avere una scroll infinita e ho bisogno di sostituire la funzione di timeout $ demo con una richiesta $ http. Ma non riesco ad arrivare alla soluzione giusta. Nel codice sottostante, lo scroll infinito funziona bene ma non mostra i dati dalla richiesta http. Il problema è che non conosco il modo di associare il risultato $ http a infiniteItems.

Here è il plunker.

Index.HTML

<body ng-app="infiniteScrolling" class="virtualRepeatdemoInfiniteScroll"> 
<div ng-controller="AppCtrl as ctrl" ng-cloak> 
    <md-content layout="column"> 
     <md-virtual-repeat-container id="vertical-container" flex> 
      <div md-virtual-repeat="item in ctrl.infiniteItems" md-on-demand 
       class="repeated-item" flex> 
       {{item.id}} 
      </div> 
     </md-virtual-repeat-container> 
    </md-content> 
</div> 
</body> 

JS:

(function() { 
'use strict'; 
angular 
    .module('infiniteScrolling', ['ngMaterial']) 
    .controller('AppCtrl', function ($timeout,$scope,$http) { 
    this.infiniteItems = { 
      numLoaded_: 0, 
      toLoad_: 0, 
      items:[], 
      getItemAtIndex: function (index) { 
       if (index > this.numLoaded_) { 
        this.fetchMoreItems_(index); 
        return null; 
       } 
       return index; 
      }, 
      getLength: function() { 
       return this.numLoaded_ + 5; 
      }, 
      fetchMoreItems_: function (index) { 
       if (this.toLoad_ < index) { 
        this.toLoad_ += 20; 

        $http.get('items.json').success(function (data) { 
         var items = data; 
         for (var i = 0; i < items.length; i++) { 
          this.items.push(items[i].data); 
         } 
         this.numLoaded_ = this.toLoad_; 
        }.bind(this)); 
       } 
      } 
     }; 
    }); 
})(); 

risposta

11

questo funziona:

plnkr

  • getItemAtIndex restituito l'indice e non l'oggetto
  • se ispezionato cosa ti ha spinto, si vedrebbe che alla linea 33 nel mio plunkr I concat obj.data, non semplice obj
(function() { 
    'use strict'; 
    angular.module('infiniteScrolling', ['ngMaterial']) 
     .controller('AppCtrl', function ($scope, $http) { 
      // In this example, we set up our model using a plain object. 
      // Using a class works too. All that matters is that we implement 
      // getItemAtIndex and getLength. 
      var vm = this; 
      vm.infiniteItems = { 
       numLoaded_: 0, 
       toLoad_: 0, 
       items: [], 

       // Required. 
       getItemAtIndex: function (index) { 
        if (index > this.numLoaded_) { 
         this.fetchMoreItems_(index); 
         return null; 
        } 
        return this.items[index]; 
       }, 

       // Required. 
       getLength: function() { 
        return this.numLoaded_ + 5; 
       }, 

       fetchMoreItems_: function (index) { 
        if (this.toLoad_ < index) { 
         this.toLoad_ += 5; 
         $http.get('items.json').then(angular.bind(this, function (obj) { 
          this.items = this.items.concat(obj.data); 
          this.numLoaded_ = this.toLoad_; 
         })); 
        } 
       } 
      } 
     }) 
})(); 
+0

Grazie, funziona. Ma non so perché per Load _ + = 20, quando scendo lo scroll i dati caricano con un grande ritardo, molto in basso non carica mai lo stesso per toLoad _ + = 10. –

+0

Beh, in realtà crea un elemento nel DOM ma poiché la tua API restituisce 5 elementi, iirc, non ha abbastanza dati da inizializzare, quindi sono vuoti/vuoti. –

+1

Grazie, hai ragione. Voglio solo aggiungere un altro punto: penso che la sostituzione di 'data' con' obj.data' non fa parte della soluzione poiché stavo usando 'success' invece di' then' e restituisce i dati non come risultato, ma usando 'concat 'è parte della soluzione. Perché quando rimuovo che il codice non funziona correttamente. Ha uno svantaggio in quanto memorizza tutti i dati (tutti i dati non visibili) in memoria, non solo i dati in vista. –

0

On ogni chiamata API tenta di ottenere che il db ha pochi record o meno. e aggiungi questa condizione nella funzione fetchMoreItems_.

fetchMoreItems_: function (index) { 
       if (this.toLoad_ < index && hasMoreRecords) { 
        this.toLoad_ += 5; 

Nel nostro codice si ottengono i dettagli come

  • sCurrentPage: 3
  • smore: true == >> questo indica che il db ha più record o non dopo pagina recupero dati saggi .
  • sTotalPages: 4
  • sTotalRecords: 36
+0

E il tuo modo di dire crea un elemento nel DOM e se otteniamo record minori che mostrano i record vuoti. Quindi, come posso rimuovere o interrompere la generazione di quei record vuoti. Puoi per favore aiutare ... –

0

venuto qui e ho visto @ risposta alessandro-Buggin che era molto disponibile. Ho dovuto cambiarlo un po ', quindi ho pensato di condividerlo per aiutare gli altri. Avevo bisogno di:

  • per evitare richieste di scorrimento, mentre già il recupero dei dati (utilizzando this.hold)
  • le richieste di arresto quando l'intero dati sono stati ricevuti dal backend (utilizzando this.stop_)
  • nascondere il contenuto durante il caricamento, a evitare glitch o elementi vuoti (sempre usando this.hold). Dal punto di vista è necessario utilizzare ng-hide su quell'elemento perché ng-if evitare che l'elemento sia mai esistito in modo che non venga caricato la prima volta.
  • implementazione di un metodo di aggiornamento per ricaricare i dati quando parametri/filtri sono stati modificati da un modulo esterno.

Lontano da perfetto ma funziona piuttosto bene.

vm.elements = null; 
vm.infiniteItems = { // Start of infinte logic 

stop_: false, 
hold: false, 
numLoaded_: 0, 
toLoad_: 0, 
items: [], 

refresh: function() { 
    this.stop_ = false; 
    this.hold = false; 
    this.numLoaded_ = 0; 
    this.toLoad_ = 0; 
    this.items = []; 
}, 

getItemAtIndex: function (index) { 
    if (!this.hold) { 
     if (index > this.numLoaded_) { 
      this.fetchMoreItems_(index); 
      return null; 
     } 
    } 
    return this.items[index]; 
}, 

getLength: function() { 
    if (this.stop_) { 
     return this.items.length; 
    } 
    return this.numLoaded_ + 5; 
}, 

fetchMoreItems_: function (index) { 
    if (this.toLoad_ < index) { 

     this.hold = true; 
     this.toLoad_ += 5; 

     var start = this.numLoaded_; 
     if (start > 0) start++; 

     MyService.getData(parameters) 
     .then(angular.bind(this, function (obj) { 

      if (obj && obj.elements > 0) { 
      vm.elements = obj.elements; 
      this.items = this.items.concat(obj.data); 

      if (obj.elements < this.toLoad_) { 
       this.stop_ = true; 
      } 
      this.numLoaded_ = this.items.length; 
      this.hold = false; 

      } else { // if no data 
      vm.elements = 0; 
      } 
     })); 
    } 
} 

} // End of infinte logic 

Nota: il mio servizio restituisce un oggetto composto in questo modo: obj = {elements: INTEGER, data: ARRAY} dove gli elementi si dice la lunghezza del pieno query.

Problemi correlati