ngx-datatable: Server pagination not working

Pagination and Sorting should be handled through the server. To load my data from the backend I´m using the following method:

this.loadData('sortColumn', 'ASC', this.currentPage, this.options.limit)
        .subscribe(ratings => {
        this.rows = [];
        this.rows.push(...ratings.ratings);
        this.endRow = this.options.limit * (this.options.offset + 1);
        this.maxRows = ratings.recordsTotal;
        if (this.maxRows < this.options.limit) {
          this.endRow = this.maxRows;
        } else if (this.maxRows < this.endRow) {
          this.endRow = this.maxRows;
        }
        this.options.count = this.maxRows;
  }, error => this.errorMessage = <any>error);}

this.rows is the variable I´m binding to the data-table-template:

<datatable class="rating_table" [rows]='rows' [options]='options' (onRowClick)='onRowClick($event)' (onPageChange)='onPage($event)'>

My problem is when I´m loading the first page the data binding ( this.rows.push(…ratings.ratings)) works and in the table my ratings are shown, but when I´m loading the second page the new ratings are saved into the this.rows object but the table is not refreshing the ratings from page one are still visible.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 4
  • Comments: 53 (14 by maintainers)

Most upvoted comments

Is there any progress on this? I think this is a critical bug.

@stefmabo - can you PR this?

No more error which is great, but only shows results on page one. Even though the new data is in there and correctly ordered. Even stranger if you just concat the old and new arrays on page change instead of splicing it works but that creates a massive array after a few pages.

Why does it even need the old data in there? Doesn’t make sense for server based data.

@amcdnl any update on this?

Maybe they should drop the demo then, its pretty misleading.

Any update on when we can expect real server-side pagination?

I’m testing it before to do a PR. I don’t know if commenting that line of code, can affect other components, then I prefer check it and after that, I will do a PR.

For now, go into node_modules/@swimlane/ngx-datatable/release/index.js a find with ctrl+f updateIndexes method and the first line of code after else is:

first = Math.max(this.offset * this.pageSize, 0);

Comment that and go here: https://github.com/swimlane/ngx-datatable/issues/138#issuecomment-282727332

I have been struggling with this issue also, and i found a solution for now. I took the sample code from: https://github.com/swimlane/ngx-datatable/blob/master/demo/paging/paging-server.ts and found that in case of server side paging with an API, there is actually 1 thing incorrect: where you loop over the rows, the sample uses i as indexer, which is correct in case of a json file with all data, however if you run it against an API, you usually get only the result set of a page, so changing the source code to the snippet below will make your server side paging on an API work

   var j = 0;
   for (let i = start; i < end; i++) {
        rows[i] = results[j];
                j++;
   }

@stefmabo, I’m confused at what you are trying to do. Are you trying to fetch data from a web server but without pagination?

Just fetch it with a service outside of this library and pass in the data to a rows array. Make server side pagination false. I think this help is better suited for StackOverflow.

I load data (cases with and without server side pagination) from a server just fine.

@stefmabo, I believe this flag already exists. externalPaging input on the table. If it is false, all of the rows are loaded client side, and if it is true, you are fetching it from a server. Is this what you meant?

@amcdnl, I believe this can be closed.

I think the solution for this specific ticket is just do not mutate the rows array, set a new one.

When is this going to be addressed? It seems to me that server side pagination should not use the offset the way client side pagination does. The entire point of server side paging is to not have to store all results in memory as the workaround does.

Edit: I should edit to say that I don’t wish to set all results to null as in the workaround because that results in the table collapsing vertically while new results are being fetched, which looks horrible.

Edit Edit: I implemented a solution that caches previous results to use as a placeholder while new results on the selected page are loading, but this is still a hefty workaround for an issue that doesn’t make sense.

i cant believe this error still exist 👎 facing that error

I have tried @dcesiel solutions => #714 . And It works properly.

@amcdnl thanks so much, really appreciate it. I’ll give it a go today.

Is this actually fixed? Cause I’ve spent hours trying to get it working and I’m kinda peeved that I’ve only just found this thread. I’m using 7.2.1 with angular v4 and getting the exact same error still.

@amcdnl Once this is fixed , can you also add this fix to 6.x.x version too? 7.0 version is not working for us, as we haven’t upgraded to angular 4 yet

@bc3 That workaround works, but the table jumps when you click next page, producing an visual error. If you edit body.component.ts > updateIndexes()

And comment a line of code like this

updateIndexes(): void {
    let first = 0;
    let last = 0;

    if (this.scrollbarV) {
      // Calculation of the first and last indexes will be based on where the
      // scrollY position would be at.  The last index would be the one
      // that shows up inside the view port the last.
      const height = parseInt(this.bodyHeight, 0);
      first = this.rowHeightsCache.getRowIndex(this.offsetY);
      last = this.rowHeightsCache.getRowIndex(height + this.offsetY) + 1;
    } else {
      //first = Math.max(this.offset * this.pageSize, 0);  Comment this!!!!!!!!!!
      last = Math.min((first + this.pageSize), this.rowCount);
    }

    this.indexes = { first, last };
  }

//first = Math.max(this.offset * this.pageSize, 0); Comment this!!!!!!!!!!

The effect of jumping dissapears.

When I show data list thought an API, it only loads data by offset and limit if the API supports pagination. I think the implementation of this datatable is based giving JSON file.

If we need to call a API to show the data, the this.indexes.first would be always 0, because the data loaded by API always start in index 0.

Then I commented this line of code //first = Math.max(this.offset * this.pageSize, 0); In my case, I never load the data using JSON file.

Go into the ngx-datatable app and edit updateIndexes()

body.component.ts

updateIndexes(): void {
    let first = 0;
    let last = 0;

    if (this.scrollbarV) {
      // Calculation of the first and last indexes will be based on where the
      // scrollY position would be at.  The last index would be the one
      // that shows up inside the view port the last.
      const height = parseInt(this.bodyHeight, 0);
      first = this.rowHeightsCache.getRowIndex(this.offsetY);
      last = this.rowHeightsCache.getRowIndex(height + this.offsetY) + 1;
    } else {
      //first = Math.max(this.offset * this.pageSize, 0); HERE!!!
      last = Math.min((first + this.pageSize), this.rowCount);
    }

    this.indexes = { first, last };
  }

Then in the component add this.

1. Variables

rows = [];
count: number = 0;
offset: number = 0;
limit: number = 10; //Whatever you want

2. ngOnInit()

ngOnInit() {
    this.fetch();
}

3. fetch()

fetch(event?) {
    if(event) this.offset = event.offset;
    this.callService.list('url', this.offset * this.limit, this.limit).subscribe(
      data => {
        this.count = data.total; //Web Service gives me the total
        this.rows = data.list; //Web Service gives me the data
      },
      null,
      () => {

      }
    );
}

4. ngx-datatable tag

<ngx-datatable
        class="material"
        ...
        (page)='fetch($event)'> <!--Here--> ...
</ngx-datatable>

Now it works using an API.

In my opinion, this datatable should have a flag to identify when we load data from JSON file or API that supports pagination.

Any development on this issue? To be honest, i can’t use the component until paging works - and i really like the look and the features of this component so i’d love to see it working.

I am currently investigating/working on server side pagination & virtual scroll problems (#353), and this seemed related.

The library does seem to cache all data, so once a page has loaded, it will remain in the rows array unless you manually clear it out like in the described workaround above.

The fix I was going to attempt was to use calculations to get the correct virtual scroll height, but try to continue leaving all of the data already loaded in the rows array because that is what it is doing now. See the conversation in #353.

Are people saying the correct behavior should be when loading new pages, the older pages should no longer be kept in memory and re-fetched when scrolling back to that page?

@java2kus, any thoughts on the discussion in this thread that might weigh into #353? Maybe this is what you were trying to convey from this comment and I just haven’t put the pieces together yet.