bind date to command object in Grails
Asked Answered
T

3

8

I have a date (as a string) being submitted. I'd like to map this to a command object. I have looked around quite a bit and found no great resource on how to do this mapping within a command object to a real date.

If I were to do this in the controller itself I could just do the following, however this doesn't allow me to easily map into my command object.

def endDate = params.date('endDate', 'MM/dd/yyyy')

For my command object, the closest I've been able to get is to override the getter and setter for the date object. Both need to be overridden or else the setter is not used. This is what I first tried (set the String to Date, but get the Date). So this doesn't use the setter:

@grails.validation.Validateable
class TaskCreateCommand {

    Date startDate


    public void setStartDate(String dateStr){
        this.start = Date.parse('MM/dd/yyyy', dateStr)
    }

}

This doesn't give any runtime problems, but is useless because I can't pull out the actual Date object.

@grails.validation.Validateable
class TaskCreateCommand {

    Date startDate


    public void setStartDate(String dateStr){
        this.start = Date.parse('MM/dd/yyyy', dateStr)
    }

    public String getStartDate(){
        return start.toString()
    }
}
Totality answered 21/6, 2013 at 18:23 Comment(1)
Was the answer helpful?Nelsen
N
6

Co-incidentally I was looking at the same problem today, and followed this answer from @Don. I was able to bind a date properly to the command object.

@Validateable
class BookCommand {
    String name
    Date pubDate
    Integer pages
}

//Controller
def index(BookCommand cmd) {
        println cmd.name
        println cmd.pages
        println cmd.pubDate

        render "Done"
    }

//src/groovy
class CustomDateEditorRegistrar implements PropertyEditorRegistrar {
    public void registerCustomEditors(PropertyEditorRegistry registry) {
        String dateFormat = 'yyyy/MM/dd'
        registry.registerCustomEditor(Date, new CustomDateEditor(new SimpleDateFormat(dateFormat), true))
    }
}

//URL
http://localhost:8080/poc_commandObject/book?name=Test&pages=10&pubDate=2012/11/11

//Println
Test
10
Sun Nov 11 00:00:00 EST 2012
Nelsen answered 21/6, 2013 at 20:22 Comment(1)
Dhiraj, How does Grails choose one if you create multiple CustomDateEditorRegistrars?Decant
M
13

If you're using Grails 2.3 or later, you can add multiple custom date formats for data binding in your Config.groovy

grails.databinding.dateFormats = ["MM/dd/yyyy"]

Then when Grails attempts to bind the request parameters to Command object properties, your custom format will be tried when parsing the date String in the request parameters eg.

class MyController {
    def myAction(MyCommandObject cmd) {
        println cmd.date
        println cmd.date.class
    }
}

class MyCommandObject {
    Date date
}

then when you hit eg.

http://localhost:8080/myController/myAction?date=12/13/2013

you should see something like ->

Fri Dec 13 00:00:00 EST 2013
class java.util.Date

on your console.

Meijer answered 30/1, 2014 at 11:39 Comment(3)
What would be the best way to handle this for Grails versions earlier than 2.3?Leprose
You'll have to register your own custom date editor which is a bit more work. Check out #2872477 for the details. It expands a bit more on how to do it than the accepted answer here.Meijer
It is better to create a ValueConverter from StringToDate like this: https://mcmap.net/q/382136/-binding-a-grails-date-from-params-in-a-controller (and it is locale aware ;))Flaherty
N
6

Co-incidentally I was looking at the same problem today, and followed this answer from @Don. I was able to bind a date properly to the command object.

@Validateable
class BookCommand {
    String name
    Date pubDate
    Integer pages
}

//Controller
def index(BookCommand cmd) {
        println cmd.name
        println cmd.pages
        println cmd.pubDate

        render "Done"
    }

//src/groovy
class CustomDateEditorRegistrar implements PropertyEditorRegistrar {
    public void registerCustomEditors(PropertyEditorRegistry registry) {
        String dateFormat = 'yyyy/MM/dd'
        registry.registerCustomEditor(Date, new CustomDateEditor(new SimpleDateFormat(dateFormat), true))
    }
}

//URL
http://localhost:8080/poc_commandObject/book?name=Test&pages=10&pubDate=2012/11/11

//Println
Test
10
Sun Nov 11 00:00:00 EST 2012
Nelsen answered 21/6, 2013 at 20:22 Comment(1)
Dhiraj, How does Grails choose one if you create multiple CustomDateEditorRegistrars?Decant
N
2

Worked for me if using the correct @BindingFormat. Example:

import grails.databinding.BindingFormat
class DateRangeFilter {
    String fieldName
    @BindingFormat('yyyy-MM-dd')
    Date from
    @BindingFormat('yyyy-MM-dd')
    Date to 
}
Nielson answered 16/8, 2019 at 6:28 Comment(1)
I posted this question in 2013 (6 years ago), so there may be an easier way in newer versions.Totality

© 2022 - 2024 — McMap. All rights reserved.