ngx-datatable: [externalPaging]="true" causes rows to disappear?

Hi,

I’m trying to use server pagination but the moment I switch the externalPaging flag to true, I’m unable to get any rows to render. I’ve tried to follow the demo code and apply it to my own situation but still haven’t got anywhere. Here’s my code at the moment:

// in view...
            <ngx-datatable
                class="material"
                [rows]="rows"
                [columns]="columns"
                [columnMode]="'force'"
                [headerHeight]="50"
                [footerHeight]="50"
                [externalPaging]="true"
                [count]="count"
                [offset]="offset"
                [limit]="limit"
                (page)="onPage($event)"    
            >
            </ngx-datatable>

// further down...
    ngOnInit() {    
        this.taskService.testWithPaging(1).subscribe((tasks) => { 
            tasks.map((task, i) => { 
                    this.rows[i++] = { id: task.id, researcher: task.researcher, details: task.details };
            });
      });
    }

I’ve verified and the taskService method returns 100 objects with the properties id, researcher and details. This works without issue when I remove the externalPaging flag (or set it to false) but having it switched on, results in nothing being shown. Is the way in which I’m populating the “rows” variable incorrect?

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 3
  • Comments: 28 (8 by maintainers)

Most upvoted comments

When paginating externally, the behaviour I’d expect is that the table component should simply output any changes of the current page and be fed with the current page rows that are retrieved externally, usually through an Http request.

From what I’ve seen, this does not happen; what happens instead is that the table component always requires the full data set and moves its offset based on the current page.

As an example, suppose I have 10 items per page, and I move to the third page: what I’d expect to happen is I get an event that signals me I need to get data for the third page (this already works); then I get the 10 items for the third page and feed them as rows to the table. What should happen now is that the table receives them and, knowing we’re using externalPaging, simply displays them; what actually happens is that the table treats them as the full data set and tries to offset them to the third page (as if we weren’t using externalPaging), resulting in an empty output.

This implies that pagination is still handled by the datatable component, and not externally, and makes the externalPaging function somewhat pointless.

Update: @amcdnl I reckon this is related to #138 , which should’ve been fixed by the pull request #714 I’m trying it out

this.count = tasks.length;

You need to set the count property to the total number of rows. If you have the count property set to 0 at the top, within your subscribe method you should set it to the length of the results returned.

@amcdnl The changelog breaking is not clear to me. “BREAKING: Fixes for external pagination fixes. Index calculation change being last page = 0 + pageSize (#714, #138, #391)

What is breaking here and what do we do to upgrade to 9.0 with existing previous version?

I have the same issue with the first load of first page.

Here an example: http://embed.plnkr.co/9d5uHNToxYJjMnQXe0Wg/

@DanjBethel @amcdnl sorry, I haven’t the time to put a demo together at the moment. However, the crux of the problem looks to be the way the rows variable is used. For instance, if your table has 50 rows per page and you’re viewing page 1, you need to make sure the rows[index] has values for [0-49] in order for the rows to render. If you then jump from page 1 to page 3, your rows variable must have values for indexes [100-149] as well as some sort of values for indexes [0-49] and [50-99].

With that said, what I’ve done for now is convert all indexes before the requested “page index” to NULL. So in short, if user requests page 3, I set indexes [0-49][50-99] to NULL values and populate [100-149] so page 3 results render. It works ok but it feels hacky and I shudder to think what will happen performance wise if a user requests a much higher page number. I suspect it works this way because the table was originally built with client-side paging in mind and I’m guessing storing the results like this in a rows var makes the paging quick and snappy?

I guess the preferred solution for server side paging would be to allow the user to feed in an ‘ad-hoc’ rows variable with indexes of [0-limit]. Of course this means that whenever you request a new page, a new request is sent so no caching is done by default, but that happens now anyway I think?

@DanjBethel Yeah, I agree! No point implementing server side paging if all you’re doing is returning the whole results set each time.

I’ve got something sort of working but it needs clean-up. Note that the sample below is simply 2 pages each with a 100 results. Takes a couple seconds to load but looks to be working. Thought I’d paste here to hopefully help you (and others) get past this initial block and perhaps we can find a more elegant solution!

So first off on page load I’m triggering the “page” function which loads the relevant page data into the rows variable.

// offset initial value = 0 
// limit initial value = 100
    ngOnInit() { 
        this.page(this.offset, this.limit);
    }

In the page function:

    page(offset, limit) {
      this.taskService.testWithPaging(offset).subscribe((tasks) => { 
          
            this.count = 200; // setting a hardcoded value of 200 for the moment to test paging between 2 pages
            this.rows = [...this.rows]; // this is necessary as we store all paging results in the row array before adding additional results from other pages. Removing this means you have to click page 1>2>1>2 before seeing the results on page 2

            tasks.map((task, i) => { 
// we simply add to the rows array where we left off before so page 2 will start from 100+index
            this.rows[((offset * limit)+ i++)] = { id: task.id, researcher: task.researcherName, details: task.details };
            });
      });
    }

Of course, I guess the “bad thing” with this is as the user clicks through pages, the row array is storing more and more results plus callbacks are happening when users click back to previously visited pages. Like I said, this is still a work in progress but hopefully helps folk.

@DanjBethel aha! Thank you, that’s solved it. I think I misunderstood the way server side paging works. I’ve created a webservice method which allows me to get the next/previous 100 results by feeding it the page number (offset). Unfortunately, it looks as though the server side paging example keeps loading the same company.json file each time instead of a different segment. I’ll have to have a play around to see if I can get the result I’m after i.e. loading a fresh batch of 100 objects per page.