'Add Offset selector to Grails Pagination
I have this grails application and I've added a number field and a button which on click passes on the query parameters, specifically the offset value so the user can navigate to a specific page faster, since the pagination has some 2000+ pages on a max=10 basis, you can imagine navigating that. Anyway, so my problem is that I'm handing the offset with jquery and all fine but when I press enter on the number field that triggers the form which is build in combination with the controller and practically filters back to page 1. So I wonder if someone knows how would I add an extra field that will pass in an offset value as well when form with filters is submitted. Sorry no code to post but this application is a monster and I suck at Grails or Spring boot in general. Any support is appreciated.
Solution 1:[1]
I'll post the answer for those who might look for this.
Grails pagination uses TwitterBootstrapTagLib class, you'll find the pagination logic there. It looks for an 'offset' variable in the session params and if it doesn't find one it creates one. Now the solution is a bit trickier than setting an 'offset' variable because when you do so you will disable the paging arrows, why? too long to explain, but trust me, you will.
To avoid having to control all the other parts of the pagination which is done perfectly well from this class you can create a new session variable, e.g. _offset, in the controller that calls the data that needs pagination.
def controllerActionX() {
...
if(params.containsKey('offset') && !params.containsKey('_offset')){
params['_offset'] = params.offset
}
...
}
You need to check first because in a second iteration you don't want to reassign offset to _offset because then you'll be stuck in one page. Also notice that offset already exists in the session, assigned by the bootstrap class.
Then you create your fields in the view:
<input type="submit" class="goto-page" id="goto-page" value="Go To Page"/>
<g:field type="number" class="topage-number" name="_offset" min="1" value="${params._offset?:1}"/>
This is self-explanatory, however, the value from the _offset field is a value entered by a human so we still need to calculate the offset based on the max records per page, i.e. in order to get page 2 on a 10 records-per-page basis, our offset has to be between 11-19, 19 preferably because it makes calculation easier.
And last step in the service layer we calculate everything like this:
def get(HttpSession session, Map params, Xclass xUser, String status) {
....
String offset = '0'
if(params.containsKey('_offset')){
if(params['_offset'] != params.offset){
params.offset = ((params._offset as int) * (max as int)) - 1
}else{
params['_offset'] = (params.offset as int) / (max as int) + 1
}
}
if (params.containsKey('offset')) offset = params.offset
...
def result = executeQuery(resultsQuery,mapping, [max: max, offset: offset])
result
That's it. Remember to cast your variables as integers when you calculate; you don't have to convert them to String after that since that is handled by the session.
By the way this is a poorly written application because the service layer should never handle any endpoint transactions, that is only a controller's job if we're following proper SOLID and MVC principles, but I found this application like this so I had to work with it.
Solution 2:[2]
Do you mean 2000 pages or rows.
Also i think if you share some few codes from your
Controller method
GSP (Thus the .gps file)
Javascript implementation
it will give a lot of people an insight on how to help us all solve the questions
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Mondi Koci |
| Solution 2 | yormen |
