1
votes

It seems simple but is apparently very hard. Bind a (finite and known length) series of checkboxes to a list of booleans on a grails command object. It should of course be possible to "populate" the command object to restore the view, with the previous selected values.

E.g I have a grails webflow. It start out by binding 4 checkboxes to an entry in a boolean list. It switches to next state and prints the values - e.g. [true,true]. Navigate back, and all the checkboxes are empty (which makes perfectly sense - 4 checkboxes and only two values). So it should rather be e.g. [false, true, false, true].

No matter what I do, I cant seem to make this happen. In spring it would be easy, simply bind the checkbox to value[0]..[3]... Why is somehthing this simple so hard in Grails?!

Please help, it would really make my day!

Example Command Obj:

class TestCmdObj {    
    List<Boolean> boolListOne = []
}

Example binding method in controller (closure executed in flow action):

private def doBindAndValidateBoolList = {       
    bindData(flow.testCmdObj, params, [include:['boolListOne']])
}

So far so good. This actually works when displaying next page in flow, the testCmdObj.boolListOne displays true for the checkboxes checked..

The GSP code is simple, and uses:

<g:checkBox name="boolListOne"/>
<g:checkBox name="boolListOne"/>
<g:checkBox name="boolListOne"/>
<g:checkBox name="boolListOne"/>

In the next view, I can print out ${testCmdObj.boolListOne} and it prints out as many "true" values, as I checked of..(e.g. [true, true]) If I navigate back, the checkboxes are emtpy... Which, again, I can understand, since they all have the same name...

2
Add the source of your command. - user800014
which source? The one that doesn't work? Which try then? .. Alright, i'll post some source code... :) - Hoof
Yep, it makes easy see what's going on :) - user800014
Hehe, yeah I know.. I just have tried so much, I was wondering which source code to post.. I'll post you my most successful try :) - Hoof
Post the command object you are trying to bind to and the HTML you are using - James Kleeh

2 Answers

0
votes

Ok, so taking this as reference:

Grails requires an command with existing list, that will be filled with data from reques.

So what you need to do is:

class TestCmdObj {
List boolListOne = ListUtils.lazyList([], FactoryUtils.instantiateFactory(Boolean) ) }

Also, your gsp will need to iterate over your command to show every entry, like:

<g:each in="${myCommandInstance.boolListOne}" var="boolInstance" status="i">
<g:checkbox name="boolListOne[${i}]" value="${boolInstance}" />
</g:each>

With this, every checkbox in your gsp will correspond as one entry in the list.

EDIT: It seems that for wrappers of primitive types there's no need for use the factory.

0
votes

Wanted to finalise all in between the above suggestions / comments.

  1. If you declare an iteration of checkboxes and callthem
<g:each in="someIteration" var="a">
  <g:checkBox name="something" value="${a.someCondition}" 
  checked="${a.someCondition}" />
</g:each>

Your controller in grails will pick up this up as String[L] A bit like a validation object of String[] something Although you would still declare this as List something=[].

This also appears to work so long as the end user has selected more than 1 checkbox. and your validation object would pickup at this point List something=[]

The issue with above is that if 1 selection is made the param is received more as a string than a list

Nothing wrong with above if you are not relying on auto binding of objects since you would do

List myList = params.list('something')

at this point grails will convert whether 1 or multiple into the list. But this won't bind a single checkbox to a validation list element.

To fix this from a validation point of view would be to declare it as List something=[]

<g:each in="someIteration" status="i" var="a">
  <g:checkBox name="something[${i}]" value="${a.someCondition}" 
   checked="${a.someCondition}" />
</g:each>

Now this will be picked up under something list like ['null','whatever','null','null'] regardless of 1 selection or multiple check box selection.

It is to use the status field and rename name from something to something[${i}]