2015-11-17 7 views
6

Używam dyrektywy md-virtual-repeat z Angular Material, aby mieć nieskończony zwój i muszę zastąpić jego funkcję demo $ z żądaniem $ http. Ale nie mogę znaleźć właściwego rozwiązania. W poniższym kodzie nieskończone przewijanie działa poprawnie, ale nie wyświetla danych z żądania http. Problem polega na tym, że nie znam sposobu wiązania wyniku $ http do infiniteItems.

Here jest 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)); 
       } 
      } 
     }; 
    }); 
})(); 

Odpowiedz

11

Ten działa:

plnkr

  • getItemAtIndex zwrócony indeks, a nie przedmiot
  • jeśli sprawdzane co popychany, można zobaczyć, że na linii 33 w moim plunkr I Concat obj.data, nie zwykły 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

Dziękuję, działa. Ale nie wiem, dlaczego doLoad _ + = 20, kiedy idę w dół przewijania danych ładuje z dużym opóźnieniem, bardzo dół nigdy nie ładuje nie to samo dla doLoad _ + = 10. –

+0

Cóż, w rzeczywistości tworzy element w DOM, ale ponieważ api zwraca 5 elementów, iirc, nie ma wystarczającej ilości danych do zainicjowania, więc są puste/puste. –

+1

Dzięki, masz rację. Chcę tylko dodać jeszcze jeden punkt: Myślę, że zastąpienie 'danych' przez' obj.data' nie jest częścią rozwiązania, ponieważ użyłem 'success' zamiast' then' i zwraca dane nie wynikowe, ale używając 'concat 'jest częścią rozwiązania. Ponieważ kiedy usunę, że kod nie działa poprawnie. Ma wadę, ponieważ przechowuje wszystkie dane (wszystkie dane z widoku) w pamięci, nie tylko dane w widoku. –

0

On każde wywołanie api spróbuj się przekonać, że db ma kilka rekordów, czy nie. i dodaj ten warunek do funkcji fetchMoreItems_.

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

W naszym kodzie możemy uzyskać szczegółowe informacje, takie jak

  • sCurrentPage: 3
  • Smore: true == >> oznacza to, że ma więcej płyt db lub nie po Pobieranie Dane mądrych .
  • sTotalPages: 4
  • sTotalRecords: 36
+0

A twoje powiedzenie tworzy element w DOM i jeśli otrzymamy mniejszą liczbę rekordów, które pokazują puste rekordy. Jak mogę usunąć lub zatrzymać generowanie pustych rekordów? Czy możesz pomóc ... –

0

przyszedł tutaj i zobaczył @ alessandro-buggin odpowiedź, która była bardzo pomocna. Musiałem to trochę zmienić, więc pomyślałem o udostępnieniu go innym, aby pomóc. Potrzebowałam:

  • aby uniknąć żądania przewijania natomiast już odzyskiwania danych (za pomocą this.hold)
  • zatrzymujące żądań kiedy cała dane otrzymane od zaplecza (używając this.stop_)
  • ukrywanie zawartości podczas ładowania, aby unikaj usterki lub pustych elementów (ponownie używając this.hold). W widoku musisz użyć elementu ng-hide na tym elemencie, ponieważ ng-if unikaj tego elementu, aby go nie załadować za pierwszym razem.
  • wdrażanie metody odświeżania w celu przeładowania danych po zmianie parametrów/filtrów z formularza zewnętrznego.

Daleko od ideału, ale działa całkiem nieźle.

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 

Uwaga: moja usługa zwraca przedmiot składający się tak: obj = {elements: INTEGER, data: ARRAY} gdzie elementy informuje o długości pełnej kwerendy.