-
Notifications
You must be signed in to change notification settings - Fork 2.5k
feat(pagination): Add custom pagination with variable page sizes #5174
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Use Case: Client requests page breaks by Date column. This can currently be accomplished by external pagination, but the 'page size' dropdown becomes irrelevant, and the page-count on the right can no longer correctly determine the correct row range. The pagination template has been modified to hide the page-size dropdown then custom pagination is enabled, and to use new API methods for the row range.
|
instead of calling reduce another time.
This looks like a very specific use case. I think I would prefer to see this in an independent plugin (or all of the pagination UI in a plugin for that matter). |
@chatcher Can you fix unit tests? |
page index and page number were confused.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made some comments on your code now. I had some questions, one request and one suggestion. Thank you for fixing the unit tests earlier however.
@@ -146,12 +176,14 @@ | |||
var visibleRows = renderableRows.filter(function (row) { return row.visible; }); | |||
grid.options.totalItems = visibleRows.length; | |||
|
|||
var firstRow = (currentPage - 1) * pageSize; | |||
var firstRow = publicApi.methods.pagination.getFirstRowIndex(); | |||
var lastRow = publicApi.methods.pagination.getLastRowIndex(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These definitions can be comma separated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
like so?
var firstRow = blahBlah(),
lastRow = blahBlah();
I don't see that pattern used elsewhere. Can you clarify what you mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that is what I meant. But I suppose you are right and we are not using this anywhere else in this project right now. It is my personal preference. No need to change it, in that case.
if (firstRow > visibleRows.length) { | ||
currentPage = grid.options.paginationCurrentPage = 1; | ||
firstRow = (currentPage - 1) * pageSize; | ||
} | ||
return visibleRows.slice(firstRow, firstRow + pageSize); | ||
return visibleRows.slice(firstRow, lastRow); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your function for getLastRowIndex doesn't appear to match the firstRow + pageSize calculation that I see here. Am I missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
firstRow
is (currentPage - 1) * pageSize
Previously, lastRow
was firstRow + pageSize
, which is algebraically
lR = fR + pS | fR = (cP - 1) * pS
= (cP-1) * pS + pS | distribute pS over (cP-1)
= cP*pS - pS + pS | cancel addition
= cP*pS
With the change, lastRow
is currentPage * pageSize
(or totalItems
), which simply eliminates the math in the middle.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the lesson in algebra right now. I should have caught that.
if (grid.options.useCustomPagination) { | ||
return publicApi.methods.pagination.getFirstRowIndex() + grid.options.paginationPageSizes[grid.options.paginationCurrentPage - 1]; | ||
} | ||
return Math.min(grid.options.paginationCurrentPage * grid.options.paginationPageSize, grid.options.totalItems); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is Math.min being used here? That doesn't appear to be there in the original function for when useCustomPagination is false. Shouldn't this be the following?
publicApi.methods.pagination.getFirstRowIndex() + grid.options.paginationPageSize
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was taken from $scope.showingHigh
(line 372), which is replaced by 1+getLastRowIndex()
.
@@ -368,8 +410,6 @@ | |||
$scope.$on('$destroy', dataChangeDereg); | |||
|
|||
var setShowing = function () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this is an empty function now. Was that on purpose? If so, what is the intention here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was in the original code; I could not find a usage or reassignment of it, but I didn't want to touch it in case I was wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -64,6 +64,8 @@ describe('ui.grid.pagination uiGridPaginationService', function () { | |||
describe('initialisation', function () { | |||
it('registers the API and methods', function () { | |||
expect(gridApi.pagination.getPage).toEqual(jasmine.any(Function)); | |||
expect(gridApi.pagination.getFirstRowIndex).toEqual(jasmine.any(Function)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should add more unit tests for these two functions than simply checking if they exist and are functions. Would you mind adding tests to ensure they return what is expected?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added tests for custom pagination.
Rather than testing getFirstRowIndex
and getLastRowIndex
directly, we test the resulting pages.
The previous tests covered one branch inside the two methods, and the tests I've added cover the other branch.
@@ -368,8 +410,6 @@ | |||
$scope.$on('$destroy', dataChangeDereg); | |||
|
|||
var setShowing = function () { | |||
$scope.showingLow = ((options.paginationCurrentPage - 1) * options.paginationPageSize) + 1; | |||
$scope.showingHigh = Math.min(options.paginationCurrentPage * options.paginationPageSize, options.totalItems); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are showingHight and last page index really the same thing? If so, how did you come to that conclusion?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The usage of showingLow
and showingHigh
was in the template to show the row range.
Instead of calculating the range here, I instead call the new methods from the template and add one there.
Since custom pagination allows for arbitrary pages of rows, we pick some feature of the existing data to paginate by. I've chosen the approximate number of pencil strokes to write the letters on column 2 (with a line through 'Z' so that it gets four strokes, and we can have two pages with 4 rows).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Defend usage of
Math.min()
ingetLastRowIndex()
. -
Address comma-separated var declarations. - Clarify calculation changes on
getLastRowIndex()
- Remove empty
setShowing()
function and related watcher. - Defend removal of
showingLow
andshowingHigh
. - Add more unit tests to ensure quality.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your changes!
Use Case:
Client requests page breaks by (e.g.) Date column. This can currently be
accomplished by external pagination, but the 'page size' dropdown
becomes irrelevant, and the page-count on the right can no longer
correctly determine the correct row range.
The pagination template has been modified to hide the page-size dropdown
when custom pagination is enabled, and to use new API methods for the
row range.
A new tutorial page has been added as lesson 406-Custom-Pagination
which demonstrates two usages: pre-sorted data, with pre-calculated pages
sizes; and unsorted data, with external pagination.