Search code examples
javascriptvue.jscoffeescriptag-gridag-grid-vue

Ag-Grid resets scroll on new datasource


I update my data outside of Ag-Grid related code. I have a variable, this.works, which stores all of the user's "portfolio" for my portfolio manager project. I have this.loadMore() which loads in more data from the server (which I do not have access to, which is why I load data externally).

I'm employing the "infinite" row model to have infinite scroll. I started using datasource because I want to use sorting and filtering, too.

The problem is that when I update the datasource, scrolling gets reset to the top. This is very annoying behaviour.

Using Ag-Grid Community and Vue.js.

GridOptions (set in beforeMount())

  this.gridOptions = {
    suppressScrollOnNewData: true,
    rowSelection: 'single',
    rowModelType: 'infinite',
    deltaRowDataMode: true,
    defaultColDef: {
      sortable: false,
      resizable: true
    },
    columnTypes: {
      'imageColumn': {
        width: 150,
        sortable: false,
        autoHeight: true,
        cellRendererFramework: AgGridImageFormatter
      },
      'priceColumn': {
        cellRendererFramework: AgGridPriceFormatter
      }
    }
  };

Methods:

({
  methods: {
    onBodyScroll: function(event) {
      var lastDisplayedWork, ref, worksCount;
      worksCount = this.works.length;
      lastDisplayedWork = (ref = this.gridOptions.api) != null ? ref.getLastDisplayedRow() : void 0;
      if (worksCount - 2 < lastDisplayedWork) {
        event.api.ensureIndexVisible(worksCount - 2);
        this.loadMore();
        return event.api.setDatasource(this.gridDatasource);
      }
    },
    CreateAgGridDataSource: function(worksData) {
      return {
        rowCount: this.works.length,
        getRows: (function(_this) {
          return function(params) {
            var lastRow, rowsThisPage;
            rowsThisPage = _this.works.slice(params.startRow, params.endRow);
            lastRow = -1;
            return params.successCallback(rowsThisPage, lastRow);
          };
        })(this)
      };
    },
    onRowSelected: function(event) {
      return this.workClicked(event.data.id);
    },
    onGridReady: function(event) {
      this.gridDatasource = this.CreateAgGridDataSource(this.works);
      return event.api.setDatasource(this.gridDatasource);
    }
  }
});

Apologies for any weird JS code, I'm using a CoffeeScript to JS converter. I think it should be ok though.

HTML:

<div id="gridContainer">
    <ag-grid-vue class="ag-theme-balham" id="AgGrid" :gridOptions="gridOptions" :modules="agGridModules" :columnDefs="agGridColDefs" @body-scroll="onBodyScroll" @row-selected="onRowSelected" @grid-ready="onGridReady"></ag-grid-vue>
</div>

How can I make sure that the scroll stays wherever the user has scrolled to? For the record, using api.refreshCells() doesn't work. With that I get blank rows after the first data call (so only the first ~23 or so items display). So, I need to "refresh" the datasource each time new data is fetched.


Solution

  • This isn't going to be an appropriate answer for everyone but my company went ahead and bought the Enterprise Ag-Grid. This gave me access to the Server Side Row Model, which in turn gives you the opportunity to only render certain rows. I can mimic server fetching inside the data source fetch, then only render the rows that were returned. This is adequate for us because we have the license - I don't think this sort of thing is possible with community edition.