0
votes

I've scoured the web for almost a day and can't seem to find a solution to my problem.
I have a lookup table called Hobby which has a bunch of hobbies in it (camping, hiking, biking, etc). The hobbies table is populated during the bootstrap. Grails creates a hobby table with an id, and description field.

I have a domain object called Applicant. An applicant can have zero or more hobbies. I've declared the domain like this:

class Applicant {

    static hasMany = [hobbies:Hobby]
List <Hobby> hobbies = LazyList.decorate(new ArrayList(), FactoryUtils.instantiateFactory(Hobby.class));

}

In my controller I'm using a command object for the page that will allow the applicant to select their hobbies. It is defined as:

class LifestyleCommand {

    List <Hobby> hobbies = LazyList.decorate(new ArrayList(), FactoryUtils.instantiateFactory(Hobby.class));
}

My gsp looks like this:

                <g:each var="item" in="${Hobby.list()}" status="i">

                    <g:set var="newline" value="${(i % 3) == 0 ? 'newline' : ''}" />

                    <div class="formcheckbox columns3 ${newline}">
                        <g:checkBox name="hobbies_${item.id}" optionKey="id" value="${item.id}" />
                        <label>${item.description}</label>
                    </div>

                </g:each>

The page will display all of the hobbies in the page correctly. However when I try to submit the form back to the controller the list in the LifeStyleCommand object is null. I'm not sure if my gsp has the g:checkBox variables set correctly, and I'm not sure if I declared the List in the command object correctly either. Once I get the data to be sent back to the controller, my next problem to overcome will be copying the data from the command object to the Applicant. Any help would be appreciated.

I've tried using just a plain List in the command but grails complains about type conversions when the form is submitted.

EDIT:

Here is what I got to work:

class Applicant {

    static hasMany = [hobbies:Hobby]
//I removed the List <hobby>... code
...
}

My command object:

class LifestyleCommand {
    Set <Hobby> hobbies;
}

gsp:

            <g:each in="${Hobby.list()}" var="hobby">
                <g:set var="checked" value="${ command?.hobbies.find{h->h.id == hobby.id } != null }" />
                <g:checkBox value="${checked}" name="${ 'hobby' +'[' + hobby.id + ']'}"/>${hobby.description}</td>
            </g:each>

And my new controller code:

Hobby.list().each{hobby->
    if (params["hobby[${hobby.id}]"] == 'on') {
        applicant.addToHobbies(hobby)
    }
    else if (applicant.getHobbies().contains(hobby)) {
        applicant.removeFromHobbies(hobby)
    }
}

Everything is working. There may be better ways, and I haven't done any refactoring yet but having it work is a starting point.

1
Can you post your controller ? - Alidad
I figured it out through some additional research, and paying attention to the exceptions I was getting. A good place to start is googling 'checkbox groups' which is what I was after even though I didn't know the term. Then I found a post referring to the Acegi plugin example here: grails.org/AcegiSecurity%20Plugin%20-%20Basic%20Tutorial Create the sample app and look at the source code for creating a user. It deals with multiple checkboxes and the has Many relationship. From there I had to get it working in my command object. - spock99
First I removed these lines from both my Domain and command object: List <Hobby> hobbies... - spock99

1 Answers

2
votes

The problem is with your GSP. When you need a list of objects, you have to maintain a standard name for your checkbox:

<g:checkBox name="hobbies[$i].id" ... />

This will be mapped correctly to your command list.