Grails e datas: Bind automático de atributo do tipo Date com formato customizado

Segue uma pequena receita de bolo para quem não está usando o datePicker padrão do Grails.


O Grails vem com uma tag que é a g:datePicker.

Ela serve para gerar listboxes (comboboxes) de dia, mês, ano, hora, minuto e segundo. Você pode até escolher quais desses comboboxes você quer que apareçam.

Mas há vezes que não queremos usar estes combos, e simplesmente queremos um campo texto onde o usuário pode digitar a data num formato qualquer, como por exemplo, dd/MM/yyyy, ou dd/MM/yy, ou yyyyMMdd, ou...ou...ou...

E ainda, se você tiver uma aplicação com internacionalização, aí pode ser que para usuários com Locale em português, o formato de entrada deste texto de data é dd/MM/yyyy , porém, se for em inglês, aí é MM/dd/yyyy.

Bom, o objetivo aqui é mostrar como dizer para o Grails para usar este formato de entrada de datas para que ele faça o parse automaticamente toda vez que encontrar um atributo do tipo Date em um objeto de domínio (ou um objeto Command) que ele precisa fazer o bind dos parâmetros recebidos num POST (ou GET).

Então:
1) O usuário preenche um campo input type="text", com uma data num formato que você determina, ex: MM/dd/yyyy
2) Ele envia este POST, que chega no seu Controller disponível no atributo params
3) você quer fazer o bind automático usando (digamos que meu objeto de domínio seja Pessoa, e nele haja um atributo Date dtAniversario):
Pessoa tx = new Pessoa(params)

Para isso acontecer de forma correta, e o seu atributo dtAniversario estar preenchido corretamente com um valor do tipo Date, é preciso criar um PropertyEditorRegistrar customizado para você. Crie um pacote em src/groovy , digamos com.meusistema.editor , e crie lá o seu PropertyEditorRegistrar:

package com.meusistema.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));
}

}


Perceba que para funcionar corretamente, você precisa editar os seus grails-app/i18n/messages.properties (messages_en_US.properties, messages_pt_BR.properties) para que tenham cada uma a sua configuração correta. Ex para o pt_BR:
dateFormat4y=dd/MM/yyyy

O passo seguinte é registrar este PropertyEditorRegistrar no arquivo grails-app/conf/spring/resources.groovy:
beans = {

customPropertyEditorRegistrar(com.manubia.propertyeditor.CustomPropertyEditorRegistrar) {
messageSource = ref('messageSource')
}

}

Pronto. É isso!

Abcs a todos

7 comentários:

Mauro 4 de março de 2010 11:49

Muito bom o post Felipe, eu ficava criando atributos transients no dominio para aceitar data em str. Vou agora adotar esta técnica.

Felipe Nascimento 5 de março de 2010 22:37

Obrigado pela participação e comentário Mauro. Um abc

João Paulo 6 de março de 2010 01:06

Estava conversando com o gilber exatamente sobre essa formataçao de data...
Agora vai resolver o problema!

vlw

Gilvan Albino de Souza 6 de março de 2010 02:17

Muito bom Felipe.
Preciso este post.

Gilber Albino de Souza 6 de março de 2010 17:05

Mto bom o post!, como o JP disse anteriormente, estávamos comentando sobre isso, formatação de data e número

vlw

Jonatas Pacheco Ribeiro 8 de março de 2010 17:34

Muito bom. Testado e implantado utilizando o resources.groovy, não consegui configurar no .xml mas com o .groovy funcionou de primeira. Vlw

Tiago Faustino 19 de abril de 2011 15:17

Resolve por um lado, mas cria brechas por outro. Por exemplo, se eu colocar "32/33/3333", o Validation não reclama que é data inválida. Aí, eu tenho que criar alguma outra solução que ainda estou estudando...