Thursday, June 10, 2010

Handling Select-Multiple with Grails

When a page sends multiple values with the same HTTP parameter name, Grails stuffs them into an ArrayList. That is very handy but there's an issue when the user only selects one value. When only one value is passed Grails does not put it into an array. And your code has to detect whether or not the parameter is an array.

Perhaps the best solution is to use a Command object. The following, for example, handles the user selection of one or multiple items (orders, qtys, etc.):


class BuildReturnItemsCommand {
String[] itemNo
int[] orderNo
int[] qty
BigDecimal[] unitPrice
String[] desc
}

[recent add: check out http://www.intelligrape.com/blog/2010/06/14/getting-params-attribute-as-list/ for another solution]

But, I'm lazy. If I have simple input where no validation is required, I don't want to take the time to create a command object. The following shows the preamble of a Controller closure that handles a single selection of a multiple-select list of regions:


def salesReport = {
params.regions = (params.regions)?[params.regions].flatten():null

Groovy to the rescue!
The ternary, if there is a regions parameter, stuffs the regions into a List. But, because the parameter might already be a list, it is flattened.

The following Groovy snippet tests this code:

def params = [:]
params.regions = 'West'
params.regions = (params.regions)?[params.regions].flatten():null

assert params.regions == ['West']

params.regions = ['East', 'North', 'South', 'West']
params.regions = (params.regions)?[params.regions].flatten():null

assert params.regions == ['East', 'North', 'South', 'West']

2 comments:

Rob said...

Grails now supports methods such as list(name) and int(name) on the params object so you can ensure you get a list even if the user only submits a single value.

Bhagwat said...

Have a look at this blog :

http://www.intelligrape.com/blog/2010/06/14/getting-params-attribute-as-list/