Updating from a list in Grails

This week I had the pleasure of attending both Groovy and Grails courses at Skills Matter in London. The courses were taught by Dierk König, a committer to both Groovy and Grails, and the author of Groovy in Action. He’s very knowledgeable and the courses were really interesting – I would have liked more time for advanced grails topics, but I guess you can’t fit it all in to two days!

During the course I asked for help with one of my pet grails problems – the best way to update multiple records at once from a list view. For example, you might have a set of records with a check box field, and want to tick/un-tick for several rows and then save all with a single click. We didn’t quite get it working in class, but I got some helpful advice which meant I was able to finish it off on the train home.

The domain class is nothing special:

class Person {
 String firstName
 String lastName
 boolean available
}

My PersonController looks like this (I’ve left the scaffolding in, so you get all the standard pages too):

class PersonController {
   static scaffold = true
   def multiEdit = {
      List<Person> list = Person.list()
      [personInstanceList: list]
   }

    def multiSave = { MultiplePersonCommand command ->
     command.people.each { p ->
     Person person = Person.get(p.id)
     person.properties = p.properties
     person.save()
   }
   redirect action: list
 }
}
class SinglePersonCommand {
 Integer id
 boolean available
}
class MultiplePersonCommand {
 List<SinglePersonCommand> people = [].withDefault({ new SinglePersonCommand() } )
}

The important thing here is the use of Command objects. I’ve defined these in the same class as the Controller but they could be in a separate file. The really important tip is the use of `withDefault` on the list in the MultiplePersonCommand. When the binding takes place, we can’t guarantee what order it will be in. For example it might try to bind the second list item before the first. This would cause an error without the `withDefault` method.

And finally, multiEdit.gsp looks like this:

<g:form action="multiSave">
 <g:each var="person" in="${personInstanceList}" status="i">
     <div id="person${i}">
     <g:hiddenField name='people[${i}].id' value='$person.id'/>
     <g:fieldValue bean="${person}" field="firstName"/>
     <g:checkBox name='people[${i}].available' value='1' checked="${person.available}"/>
   </div>
 </g:each>
 </div>
<g:submitButton name="action" />
</g:form>

The important thing here is the use of the $i variable in square brackets on the fields in question. This means that the params that come back to the Controller will effectively contain people[0].id, people[0].available, people[1].id, people[1].available and so on. Grails is clever enough to bind all the people[0] values to the first SinglePersonCommand in the people list inside the MultiplePersonCommand, and so on. Then I can access this list and copy across the values to People objects and save them.

I hope this is useful to someone. I’m looking forward to spending some time on Groovy and Grails development, so hopefully more here soon!

 

5 thoughts on “Updating from a list in Grails

  1. Any idea how to get this working with a multi-select? Works great with checkboxes where you have the list index (I.e. people[i].id) but I can’t seem to get it working with a g:select when multiple=true.

  2. Sorry not off the top of my head. It works with the check boxes because you also have the hidden field for each person so that you know which people you are interested in, whether checked or not.

Leave a Reply to Steven Lilley Cancel reply

Your email address will not be published. Required fields are marked *