Material angular infinite scroll with $http request

后端 未结 3 1144
轮回少年
轮回少年 2021-01-05 17:20

I\'m using md-virtual-repeat directive of Angular Material to have an infinite scroll, and I need to replace it\'s demo $timeout function with a $h

相关标签:
3条回答
  • 2021-01-05 17:48

    This one works:

    plnkr

    • getItemAtIndex returned the index and not the item
    • if you inspected what you pushed, you'd see that at line 33 in my plunkr I concat obj.data, not plain 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 讨论(0)
  • 2021-01-05 17:54

    came here and saw @alessandro-buggin answer which was very helpful. I had to change it a little bit, so I thought of sharing it for others to help. I needed:

    • to avoid getting scroll requests while already recovering data (using this.hold)
    • stopping requests when the whole data was received from the backend (using this.stop_)
    • hiding the content while loading, to avoid glitches or empty elements (again using this.hold). On the view you need to use ng-hide on that element because ng-if avoid the element to ever exist so it won't load the first time.
    • implementing a refresh method to reload data when parameters/filters changed from an outside form.

    Far from perfect but works pretty well.

    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
    

    Note: my service returns an object composed like this: obj = {elements: INTEGER, data: ARRAY} where elements tells you the length of the full query.

    0 讨论(0)
  • 2021-01-05 18:09

    On every api call try to get wheather the db has few more records or not. and add that condition in fetchMoreItems_ function.

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

    In our code we get the details like

    • sCurrentPage : 3
    • sMore: true ==>>this indicates that the db has more records or not after fetching page wise data.
    • sTotalPages: 4
    • sTotalRecords : 36
    0 讨论(0)
提交回复
热议问题