Search code examples
grailsgsp

Is there any solution to get g:pagination and g:sortableColumn for children elements in parents show view working?


Is there any simple solution to get g:pagination and g:sortableColumn for children elements in parent show view working?

It is well explained in the documentation how to do pagination and sortable columns for current domain in list, and it works, but I cant get it to work in situation described in question.

Edit: I updated the example

Now only thing that is not working is pagination. When I click on the next page link the list is gone and ${childrenistSize} prints 0.

Simple example:

Parent domain

class Parent {

    String name

    static hasMany = [children: Children]

    static constraints = {
    }
}

Children domain

class Children {

    String first
    int number

    static belongsTo = [parent: Parent]

    static constraints = {
    }
}

Parent list view

<g:each in="${parentList}" var="parent">
    <tr>
        <td>${parent.name}</td>
        <td><g:link controller="parent" action="show" id="${parent.id}">Show</g:link></td>
    </tr>
</g:each>

Parent show view

<table>
    <thead>
        <tr>
            <g:sortableColumn property="first" title="First"/>
            <g:sortableColumn property="number" title="Number"/>
        <tr>
    </thead>
    <tbody>
        <g:each in="${childrenList}" var="child">
            <tr>
                <td>${child.first}</td>
                <td>${child.number}</td>
            </tr>
        </g:each>
    </tbody>
</table>
<g:paginate total="${childrenListSize}"/>

ParentController

class ParentController {

    def index() { }

    def list() {
        [parentList: Parent.list()]

    }

    def show() {
        params.max=3
        def parentInstance = Parent.get(params.id)
        def childrens = Children.createCriteria().list(params) {
          eq('parent', parentInstance)
        }
        [parentInstance : parentInstance , childrenList: childrens, childrenListSize: childrens.totalCount]
     }

}

Some BootStrap test elements

    Parent parent1 = new Parent(name: "TestParent1")
    Parent parent2 = new Parent(name: "TestParent2")

    Children child1 = new Children(first: "Bob", number: "1")
    Children child2 = new Children(first: "John", number: "2")
    Children child3 = new Children(first: "Igor", number: "3")
    Children child4 = new Children(first: "Lucy", number: "4")
    Children child5 = new Children(first: "Lisa", number: "5")

    Children child6 = new Children(first: "Bob", number: "12")
    Children child7 = new Children(first: "John", number: "24")
    Children child8 = new Children(first: "Igor", number: "33")
    Children child9 = new Children(first: "Lucy", number: "42")

    parent1.addToChildren(child1).addToChildren(child2).addToChildren(child3).addToChildren(child4).addToChildren(child5)
    parent2.addToChildren(child6).addToChildren(child7).addToChildren(child8).addToChildren(child9)

    parent1.save()
    child1.save()
    child2.save()
    child3.save()
    child4.save()
    child5.save()
    parent2.save()
    child6.save()
    child7.save()
    child8.save()
    child9.save()

Solution

  • The problem is that you don't have a column named children.name in the Children domain class. What you need to do is identify in your controller that you must sort by the name column.

    I can see that you show a list of childrens in the show action of Parent, and the parent isn't sortable in this action, so will be a simple change:

    def show() {
      def parentInstance = Parent.get(params.id)
      def childrens = Children.createCriteria().list(params) {
        eq('parent', parentInstance)
      }
      [parentInstance : parentInstance , childrenList: childrens, childrenListSize: childrens.totalCount]
    }
    
    
    <p>Parent: ${parentInstance.name}</p>
    <table>
        <thead>
            <tr>
                <g:sortableColumn property="name" title="Name"/>
            <tr>
        </thead>
        <tbody>
            <g:each in="${childrenList}" var="child">
                <tr>
                    <td>${child.name}</td>
                </tr>
            </g:each>
        </tbody>
    </table>
    <g:paginate max="1" total="${childrenListSize}"/>
    

    Note that I changed the property name since it's just name and not children.name. Also, i pass the params to the criteria to make the sort works.

    I not tested this, so can be a typo anywhere.