7

I have built an advanced search option that allows users to search a multitude of different fields - 38 possible fields in total.

Once the initial search has been submitted, 10 results are displayed with pagination options at the bottom (using grails' <g:paginate> tag).

I think I have a few problems here.

1) I need to somehow pass the fields back to the controller using the params attribute of the g:paginate tag, but I don't really want to create a params map of 40 something parameters.

2) I pass back to the page from the Controller a map of search parameters (so that they can have a dismissable list of parameters that perform the search again without the dismissed parameter). I can pass this back in the params attribute, but it's passed back to the controller as a String and not a map so I don't know how to iterate through it (I realised this after it iterated through each separate character!).

3) The URL of the links that the g:paginate tag creates could potentially be massive, depending on how much of the search fields the user enters. Could there be a danger of the URL exceeding it's maximum amount?

I'm contemplating changing from the built in grails paginate functionality, and creating a form which I can POST. I'm not sure if this is the best way though, and I may be missing some alternative way to do this that is much better.

Any help greatly received!

Gareth Lewis
  • 751
  • 2
  • 15
  • 36
  • 1
    This might be a bit different than your current approach, have you considered sending the form using Ajax and updating the result table. Take a look at [g:formRemote](http://grails.org/doc/2.3.x/guide/theWebLayer.html#remoteFormSubmission) and [pagination plugin](http://grails.org/plugin/remote-pagination). It requires a bit change in your current architecture though. – Alidad Feb 28 '14 at 14:57
  • I'll certainly look into it. Thanks. – Gareth Lewis Mar 01 '14 at 18:31

4 Answers4

9

You can pass all your parameters to action using pageScope.variables like

<g:paginate params="${pageScope.variables}" total=.../>
MKB
  • 7,587
  • 9
  • 45
  • 71
2

index.gsp

        <div class="pagination">

            <g:paginate total="${personCount ?:0}" max="5" params="${params}" />
        </div>

Controller.groovy

def index(Integer max)
{

    def c=Person.createCriteria()
    def results
    int count
    params.max = Math.min(max ?: 5, 100)
    if(params.name != null)
    {

         params.max = 4
         if(!params.offset) 
         {
             params.offset = 0;
         }
      count = Person.countByNameLike("%"+params.name+"%")
        results=c.list{
           like("name","%"+params.name+"%")
           maxResults(params.max)
           firstResult(params.getInt("offset"))
       }

    }
    else 
    {
        results = Person.list(params)
        count = Person.count()
    }

    respond results, model:[personCount: count]
}
rstag
  • 21
  • 1
  • you should add some details to your answer, not just paste plain code. What have you done and why/how does it solve the issue? – hering Aug 21 '17 at 11:48
1

I'd put your search params into session. Thus you can use the very basic grails g.paginate tag w/o polluting it. Each time the user changes his search, the parameters should get updated.

injecteer
  • 20,038
  • 4
  • 45
  • 89
  • 2
    Keeping state of a page in session, usually results in more side effects than you are expecting. – Alidad Feb 28 '14 at 14:56
  • like what? never seen any *unexpected side effects*, if the session is used properly. Of course you can mis-use it, like pretty much any other tool – injecteer Feb 28 '14 at 15:01
  • For this particular case you need to reset it after users move out of that page. Otherwise when the page is reloaded will have the previous search params. – Alidad Feb 28 '14 at 15:04
  • This is exactly what should happen it either the page gets refreshed or if pagination links get clicked - the search criteria remain the same, but the pagination options may change w/o overloading the `GET-request` with 40+ params – injecteer Feb 28 '14 at 15:20
  • Think about changing the page after a search eg. going to home and come back to search again expecting to have a new search page, you will see the parameters from old search. – Alidad Feb 28 '14 at 15:25
  • this might well be the expected behavior. The simplest use-case: 1. a user fires up a search 2. the user goes into detail page of one hit 3. the user is coming back to search and sees the latest search results. – injecteer Feb 28 '14 at 15:33
  • 1
    Another problem with keeping search parameters in the session is that, as a user, you can't send someone a link to say page 37 of some complicated search and expect them to be able to see the same results as you. This may not be an issue for your use case, but it's worth thinking about. – rcgeorge23 Mar 01 '14 at 07:56
  • indeed, but this is not **my** case :) Dear #Gareth let us all speculating about it without giving any additional info. Anyway, saving the complex search is an important thing, but referencing page 37 doesn't make much sense if the searchable data are dynamic – injecteer Mar 01 '14 at 11:09
0

1 and 2) The best solution I found:

for the action:

def list() {
... //use params to filter you query and drop results to resultList of type PagedResultList
return [resultList: resultList, resultTotal: resultList.getTotalCount(), filterParams: params]
}

for the view:

<g:paginate total="${resultTotal}" action="list" params="${filterParams}"/>

See a complete example.

3) The url (and get parameters) limit size is 2000 (see why). If that is a problem to you, you'd better switch to an ajax solution or minimize the url size filtering only the filled params. You could accomplish that replacing this line:

return [resultList: resultList, resultTotal: resultList.getTotalCount(), filterParams: params.findAll{ it.value } ]
Community
  • 1
  • 1
Cléssio Mendes
  • 996
  • 1
  • 9
  • 25