Angular UI Grid 'gridApi.infiniteScroll.on.needLoadMoreData' doesn't work with changes in data
Asked Answered
S

3

40

I am using angular-ui-grid 3.2.5

Scrolling with gridApi.infiniteScroll.on.needLoadMoreData($scope, $scope.getDataDown) is working well, but when we are pushing new data when data changes in grid via $scope.$watch('data', updateGrid), then on the end of scrolling gridApi.infiniteScroll.on.needLoadMoreData doesn't call getDataDown method and scrolling stops although there is more data.

Here are the gridOptions:

$scope.gridOptions = {
  infiniteScrollRowsFromEnd: 40,
  infiniteScrollUp: true,
  infiniteScrollDown: true,
  enableColumnMenus: false, // Remove hide columns options
  columnDefs: $scope.myDefs,
  data: 'data',
  onRegisterApi: function (gridApi) {
    gridApi.infiniteScroll.on.needLoadMoreData($scope, $scope.getDataDown);
    gridApi.infiniteScroll.on.needLoadMoreDataTop($scope, $scope.getDataUp);
    $scope.gridApi = gridApi;
  }
};

Here's the updateGrid() implementation

function updateGrid(filteredData) {
  $scope.response = filteredData;

  $scope.firstPage = 1;
  $scope.lastPage = 1;
  $scope.totalPages = Math.ceil($scope.response.length / $scope.pageSize);

  $scope.gridApi.infiniteScroll.setScrollDirections(false, false);
  $scope.data = [];
  $scope.data = $scope.response.slice(0, $scope.pageSize);

  $timeout(function () {
    $scope.gridApi.infiniteScroll.resetScroll($scope.firstPage > 0, $scope.lastPage < $scope.totalPages);
  });
};

What could be the issue ?

Swordfish answered 24/11, 2016 at 9:20 Comment(1)
Please show the functions for $scope.getDataDown and $scope.getDataUpHefner
A
1

var app = angular.module('app', ['ngTouch', 'ui.grid', 'ui.grid.infiniteScroll']);

app.controller('MainCtrl', function ($scope, $http, $timeout) {
  var vm = this;

  vm.gridOptions = {
    infiniteScrollRowsFromEnd: 40,
    infiniteScrollUp: true,
    infiniteScrollDown: true,
    columnDefs: [
      { name:'id'},
      { name:'name' },
      { name:'age' }
    ],
    data: 'data',
    onRegisterApi: function(gridApi){
      gridApi.infiniteScroll.on.needLoadMoreData($scope, getDataDown);
      gridApi.infiniteScroll.on.needLoadMoreDataTop($scope, getDataUp);
      vm.gridApi = gridApi;
    }
  };

  $scope.data = [];

  vm.firstPage = 2;
  vm.lastPage = 2;

  function getFirstData() {
    return $http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pageshttps://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/10000_complex.json')
    .then(function(response) {
      var newData = getPage(response.data, vm.lastPage);

      $scope.data = $scope.data.concat(newData);
    });
  }

  function getDataDown() {
    return $http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pageshttps://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/10000_complex.json')
    .then(function(response) {
      vm.lastPage++;
      var newData = getPage(response.data, vm.lastPage);
      vm.gridApi.infiniteScroll.saveScrollPercentage();
      $scope.data = $scope.data.concat(newData);
      return vm.gridApi.infiniteScroll.dataLoaded(vm.firstPage > 0, vm.lastPage < 4).then(function() {checkDataLength('up');});
    })
    .catch(function(error) {
      return vm.gridApi.infiniteScroll.dataLoaded();
    });
  }

  function getDataUp() {
    return $http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pageshttps://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/10000_complex.json')
    .then(function(response) {
      vm.firstPage--;
      var newData = getPage(response.data, vm.firstPage);
      vm.gridApi.infiniteScroll.saveScrollPercentage();
      $scope.data = newData.concat($scope.data);
      return vm.gridApi.infiniteScroll.dataLoaded(vm.firstPage > 0, vm.lastPage < 4).then(function() {checkDataLength('down');});
    })
    .catch(function(error) {
      return vm.gridApi.infiniteScroll.dataLoaded();
    });
  }

  function getPage(data, page) {
    var res = [];
    for (var i = (page * 100); i < (page + 1) * 100 && i < data.length; ++i) {
      res.push(data[i]);
    }
    return res;
  }

  function checkDataLength( discardDirection) {
    // work out whether we need to discard a page, if so discard from the direction passed in
    if( vm.lastPage - vm.firstPage > 3 ){
      // we want to remove a page
      vm.gridApi.infiniteScroll.saveScrollPercentage();

      if( discardDirection === 'up' ){
        $scope.data = $scope.data.slice(100);
        vm.firstPage++;
        $timeout(function() {
          // wait for grid to ingest data changes
          vm.gridApi.infiniteScroll.dataRemovedTop(vm.firstPage > 0, vm.lastPage < 4);
        });
      } else {
        $scope.data = $scope.data.slice(0, 400);
        vm.lastPage--;
        $timeout(function() {
          // wait for grid to ingest data changes
          vm.gridApi.infiniteScroll.dataRemovedBottom(vm.firstPage > 0, vm.lastPage < 4);
        });
      }
    }
  }

  vm.reset = function() {
    vm.firstPage = 2;
    vm.lastPage = 2;

    // turn off the infinite scroll handling up and down - hopefully this won't be needed after @swalters scrolling changes
    vm.gridApi.infiniteScroll.setScrollDirections( false, false );
    $scope.data = [];

    getFirstData().then(function(){
      $timeout(function() {
        // timeout needed to allow digest cycle to complete,and grid to finish ingesting the data
        vm.gridApi.infiniteScroll.resetScroll( vm.firstPage > 0, vm.lastPage < 4 );
      });
    });
  };

  getFirstData().then(function(){
    $timeout(function() {
      // timeout needed to allow digest cycle to complete,and grid to finish ingesting the data
      // you need to call resetData once you've loaded your data if you want to enable scroll up,
      // it adjusts the scroll position down one pixel so that we can generate scroll up events
      vm.gridApi.infiniteScroll.resetScroll( vm.firstPage > 0, vm.lastPage < 4 );
    });
  });
});
.grid {
  width: 500px;
  height: 400px;
}
<!doctype html>
<html>
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular-touch.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular-animate.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular-aria.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/4.7.1/ui-grid.min.js"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/angular-ui/bower-ui-grid/ui-grid.min.css" type="text/css">

  </head>
  <body ng-app="app"> 
<div ng-controller="MainCtrl as $ctrl">
  <button id="reset" class="button" ng-click="$ctrl.reset()">Reset</button>
  <span> &nbsp; &nbsp; First page: {{ $ctrl.firstPage }} &nbsp; &nbsp; Last page: {{ $ctrl.lastPage }}  &nbsp; &nbsp; data.length: {{ data.length }} </span>
  <div ui-grid="$ctrl.gridOptions" class="grid" ui-grid-infinite-scroll></div>
</div>
  </body>
</html>

If you can update ui.grid to the last version. I found this example for you, but if you don't pu these functions getDataDown and getDataUp, i can't fix you.

Auberbach answered 18/2, 2019 at 14:2 Comment(0)
V
0

I had the same issue I solved it as below. That is happening because I assume you haven't implemented your needLoadMoreDataTop function. Just add the below code and you should be good. Also set infiniteScrollUp as true on grid options.

_.invoke(gridApi, 'infiniteScroll.on.needLoadMoreDataTop', $scope , topFunction);

function topFunction() {
  gridApi.infiniteScroll.dataLoaded(true,true);
}
Vitamin answered 13/7, 2019 at 0:10 Comment(0)
K
0

var app = angular.module('app', ['ngTouch', 'ui.grid', 'ui.grid.infiniteScroll']);

app.controller('MainCtrl', function ($scope, $http, $timeout) {
  var vm = this;

  vm.gridOptions = {
    infiniteScrollRowsFromEnd: 40,
    infiniteScrollUp: true,
    infiniteScrollDown: true,
    columnDefs: [
      { name:'id'},
      { name:'name' },
      { name:'age' }
    ],
    data: 'data',
    onRegisterApi: function(gridApi){
      gridApi.infiniteScroll.on.needLoadMoreData($scope, getDataDown);
      gridApi.infiniteScroll.on.needLoadMoreDataTop($scope, getDataUp);
      vm.gridApi = gridApi;
    }
  };

  $scope.data = [];

  vm.firstPage = 5;
  vm.lastPage = 5;

  function getFirstData() {
    return $http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pageshttps://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/10000_complex.json')
    .then(function(response) {
      var newData = getPage(response.data, vm.lastPage);

      $scope.data = $scope.data.concat(newData);
    });
  }

  function getDataDown() {
    return $http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pageshttps://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/10000_complex.json')
    .then(function(response) {
      vm.lastPage++;
      var newData = getPage(response.data, vm.lastPage);
      vm.gridApi.infiniteScroll.saveScrollPercentage();
      $scope.data = $scope.data.concat(newData);
      return vm.gridApi.infiniteScroll.dataLoaded(vm.firstPage > 0, vm.lastPage < 5).then(function() {checkDataLength('up');});
    })
    .catch(function(error) {
      return vm.gridApi.infiniteScroll.dataLoaded();
    });
  }

  function getDataUp() {
    return $http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pageshttps://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/10000_complex.json')
    .then(function(response) {
      vm.firstPage--;
      var newData = getPage(response.data, vm.firstPage);
      vm.gridApi.infiniteScroll.saveScrollPercentage();
      $scope.data = newData.concat($scope.data);
      return vm.gridApi.infiniteScroll.dataLoaded(vm.firstPage > 0, vm.lastPage < 5).then(function() {checkDataLength('down');});
    })
    .catch(function(error) {
      return vm.gridApi.infiniteScroll.dataLoaded();
    });
  }

  function getPage(data, page) {
    var res = [];
    for (var i = (page * 100); i < (page + 1) * 100 && i < data.length; ++i) {
      res.push(data[i]);
    }
    return res;
  }

  function checkDataLength( discardDirection) {
    // work out whether we need to discard a page, if so discard from the direction passed in
    if( vm.lastPage - vm.firstPage > 3 ){
      // we want to remove a page
      vm.gridApi.infiniteScroll.saveScrollPercentage();

      if( discardDirection === 'up' ){
        $scope.data = $scope.data.slice(100);
        vm.firstPage++;
        $timeout(function() {
          // wait for grid to ingest data changes
          vm.gridApi.infiniteScroll.dataRemovedTop(vm.firstPage > 0, vm.lastPage < 5);
        });
      } else {
        $scope.data = $scope.data.slice(0, 400);
        vm.lastPage--;
        $timeout(function() {
          // wait for grid to ingest data changes
          vm.gridApi.infiniteScroll.dataRemovedBottom(vm.firstPage > 0, vm.lastPage < 4);
        });
      }
    }
  }

  vm.reset = function() {
    vm.firstPage = 5;
    vm.lastPage = 5;

    // turn off the infinite scroll handling up and down - hopefully this won't be needed after @swalters scrolling changes
    vm.gridApi.infiniteScroll.setScrollDirections( false, false );
    $scope.data = [];

    getFirstData().then(function(){
      $timeout(function() {
        // timeout needed to allow digest cycle to complete,and grid to finish ingesting the data
        vm.gridApi.infiniteScroll.resetScroll( vm.firstPage > 0, vm.lastPage < 5 );
      });
    });
  };

  getFirstData().then(function(){
    $timeout(function() {
      // timeout needed to allow digest cycle to complete,and grid to finish ingesting the data
      // you need to call resetData once you've loaded your data if you want to enable scroll up,
      // it adjusts the scroll position down one pixel so that we can generate scroll up events
      vm.gridApi.infiniteScroll.resetScroll( vm.firstPage > 0, vm.lastPage < 5 );
    });
  });
});
.grid {
  width: 400px;
  height: 400px;
}
<!doctype html>
<html>
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular-touch.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular-animate.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular-aria.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/4.7.1/ui-grid.min.js"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/angular-ui/bower-ui-grid/ui-grid.min.css" type="text/css">

  </head>
  <body ng-app="app"> 
<div ng-controller="MainCtrl as $ctrl">
  <button id="reset" class="button" ng-click="$ctrl.reset()">Reset</button>
  <span> &nbsp; &nbsp; First page: {{ $ctrl.firstPage }} &nbsp; &nbsp; Last page: {{ $ctrl.lastPage }}  &nbsp; &nbsp; data.length: {{ data.length }} </span>
  <div ui-grid="$ctrl.gridOptions" class="grid" ui-grid-infinite-scroll></div>
</div>
  </body>
</html>
Kobold answered 20/2, 2021 at 7:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.