Friday, March 12, 2010

Grails and Dates: automatic binding a Date attribute from a custom formatted string

Here is a small recipe for those who are not using the DatePicker default Grails.
The Grails comes with a tag that is g:datepicker. It generates listboxes (comboboxes) for day, month, year, hour, minute and second. You can even choose which of these comboboxes you want to generate.

But there are times we do not want to use these combos, and just want a text field where the user can type the date in any format, such as dd/MM/yyyy or dd/MM/yy, or yyyyMMdd, or .. . ... or ... or

Also, if you have an internationalized application, there may users with Portuguese Locale and input format like dd/MM/yyyy, or others with an English Locale and MM/dd/yyyy format.

Well, the goal here is to show how to configure Grails to use different input formats for dates, so it can parse automatically whenever you have an attribute of type Date in a domain object (or a Command object) that we need to bind from the parameters received in a POST (or GET).

Here it goes:
1) User fills out a field input type = "text", with a date in a format that you determine, ex: MM/dd/yyyy
2) He/she sends this POST, which gets to your Controller and you have the params attribute
3) you want to automaticaly  bind (let's say my domain object is Person, and in it there is a Date birthday):
Person p = new Person(params)  

For this to happen correctly, and its birthday attribute be binded with a value of type Date, you must create a PropertyEditorRegistrar customized for you. Create a package in src/groovy, say com.myapp.editor and create there a PropertyEditorRegistrar:

package com.myapp.editor; 
 import java.text.SimpleDateFormat; 
 import java.util.Date; 
 import org.springframework.beans.PropertyEditorRegistrar; 
 import org.springframework.beans.PropertyEditorRegistry; 
 import org.springframework.beans.propertyeditors.CustomDateEditor; 
 import org.springframework.context.i18n.LocaleContextHolder; 
 public class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar { 
  def messageSource; 
  public void registerCustomEditors(PropertyEditorRegistry registry) { 
    registry.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat(messageSource.getMessage("dateFormat4y",null,'dd/MM/yyyy',LocaleContextHolder.locale )),true)); 

Note that to work properly, you need to edit your grails-app/i18n/ (, to have each one its correct setting. Ex for the en:

The next step is to register this PropertyEditorRegistrar in the grails-app/conf/spring/resources.groovy:
beans = { 
  customPropertyEditorRegistrar(com.myapp.editor.CustomPropertyEditorRegistrar) { 
     messageSource = ref('messageSource') 

That's it!