Ray
Ray

Reputation: 6095

grails list not returning all, even with no max/offset specified, in g:sortableColumn

Background: The g:sortableColumn tag by default invokes the list action in a controller, passing it a "sort" parameter, which indicates which field to sort by. In my specific case, I have an Issue class/list that I'm sorting:

 class Issue {
     String title 
          ...
     User assignedTo
          ...
  }

and

 Class User {
    String lastName
     ...
 }

Specifying a g:sortableColumn property="assignedTo.lastName", which translates into the sort parameter of the list, works great if the issue has been assigned -- i.e. assignedTo is non null. But if it hasn't, then list() no longer returns it. I don't know if this is a fault of list() or not (comments?), but I'd like to have those Issues with a null assignedTo come at the end.

I thought about combining Issue.list() with an Issue.findAllByAssignedToIsNull(), but it will require coordinating max/offset in both, which I'd rather avoid if possible.

Thoughts/comments?

------- per comment ------

It is the standard (Grails 1.3.7) scaffolded list action, i.e.:

   def list = {
    params.max = Math.min(params.max ? params.int('max') : 10, 100)
    [issueInstanceList: Issue.list(params), issueInstanceTotal: Issue.count()]
}

----- per second comment (mine) ----------------------------------------

I also tried the following, once again it did not return the Issues where assignedTo was null:

 <g:sortableColumn property="assignedTo.lastName" title="${message(code: 'issue.assignedTo.label', default: 'Assigned To')}" />

 def list = {
   if (params.sort == 'assignedTo.lastName') {
      println "doing special find/sort by: ${params.sort}"
      return [issueInstanceList: Issue.findAllByAssignedToIsNullOrAssignedToIsNotNull(params), issueInstanceTotal: Issue.count()]
   }
   [issueInstanceList: Issue.list(params), issueInstanceTotal: Issue.count()]
 } 

Upvotes: 1

Views: 1118

Answers (2)

jenk
jenk

Reputation: 1043

As i understood g:sortableColumn does not depend on bean object (in this case class User), but uses it's class properties.

property="assignedTo.lastName"

always have to be work, because of it is used in 'order by' and 'sort' statements of query

Upvotes: 0

ataylor
ataylor

Reputation: 66059

You have to force a left join on the user table. Here's one way to do it with a criteria query:

import org.hibernate.criterion.CriteriaSpecification

...

def list() {
    params.max = Math.min(params.max ? params.int('max') : 10, 100)
    def criteriaParams = [:]
    criteriaParams.putAll(params)
    def sortParam = criteriaParams.remove('sort')
    def orderParam = criteriaParams.remove('order')
    def issueList = Issue.createCriteria().list(criteriaParams) {
        createAlias('assignedTo', 'assignedTo', CriteriaSpecification.LEFT_JOIN)
        if (sortParam) {
            order(sortParam, orderParam)
        }
    }

    [issueInstanceList: issueList, issueInstanceTotal: issueList.getTotalCount()]
}

Passing params into the criteria list() method automatically handles pagination and sorting, just like the domain object list() method. Our createAlias happens too late though, so we have to remove sort and order, then reapply them manually after creating an alias forcing the left join.

Upvotes: 1

Related Questions