backbone-paginator/backbone-pageable

Pagination fails with no results

jbraithwaite opened this issue · 16 comments

I'm using pagination with a filter which means my API needs to return zero results sometimes. This causes the following Range Error to be thrown:

Uncaught RangeError: `currentPage` must be firstPage <= currentPage <= totalPages if 1-based. Got 1.

Where:

> firstPage
1

> currentPage
1

> totalPages
0

Even if I set totalPages to 1 in my API it gets set to zero which is causing the error to be thrown.

Can you paste a log of the state metadata in your response body here?

This is on the last time _checkState() is fired

{
  currentPage: 1
  filterStatus: undefined
  filterText: undefined
  firstPage: 1
  lastPage: 0
  order: null
  pageSize: 15
  sortKey: null
  totalPages: 0
  totalRecords: 0
}

It fires three times when I do a get*Page. Screen Shot 2013-02-09 at 2 25 35 AM

You don't have to return so many states in your response body, you just have to return totalRecords, and everything else will be recalculated when necessary. Alternatively, you can set totalRecords to null instead of 0 to skip _checkState.

Returning null worked like a charm!

It seems that issue with processing 0 in totalRecords is about totalPages calculation:
totalPages = state.totalPages = ceil(totalRecords / pageSize)

Assuming that firstPage === 1 for empty response, should the totalPages become 1 also?

Why would an empty response indicate having > 0 number of pages?

Considering the following condition:
firstPage === 1 && (currentPage < firstPage || currentPage > totalPages)

The state has firstPage === 1, currentPage === 1 and firstPage === 1. Passing condition leads to RangeError throwing. So there are two approaches: keep all related state properties actual (being 0) in case of totalRecords === 0 or force totalPages = 1 in this case.

As for me, server API should response only with total_entries === 0 in case of empty collection (e.g. after filtration). So the question is: should it be treated as first and single page (totalPages === 1)? If not, then the only way is to respond with total_entries === null (which makes server API less consistent).

The better question is, under what circumstances would you ever reach that state by using the paginator's methods? Are you manually fiddling the state yourself?

Yes, I'm setting state.currentPage = 1. But before fetching the filtered results.

Would this work for you?

else if (firstPage === 1 && (currentPage < firstPage || currentPage > totalPages && totalPages > 0)) {

Also, which mode are you using?

I'm using the "server" mode and yes - this condition works. So the question is about which workaround to use - && totalPages > 0 or ceil(totalRecords / pageSize) || 1. Your one assumes that state.totalPages really should stay 0. It seems that we are about some "domain" choice - is it correct to say that we have a page for empty collection or not?

Can you obtain a grain of salt from an empty jar? That's a contradiction. I'll commit a fix for this. Thanks for letting me know.

But a jar is not supposed to disappear due to lack of salt :) Anyway, thanks a lot.

What if ?
currentPage: 4
firstPage: 1
pageSize: 10
totalPages: 1
totalRecords: 5

I am getting same issue! Plz help!

How can you have a totalRecords of 5, a pageSize of 10 and be on page 4? Of course you get an error.