Binding a Grails date from params in a controller

2019-01-03 08:47发布

Why is it so hard to extract the date from the view via the params in a grails controller?

I don't want to extract the date by hand like this:

instance.dateX = parseDate(params["dateX_value"])//parseDate is from my helper class

I just want to use instance.properties = params.

In the model the type is java.util.Date and in the params is all the information: [dateX_month: 'value', dateX_day: 'value', ...]

I searched on the net and found nothing on this. I hoped that Grails 1.3.0 could help but still the same thing.

I can't and will not believe that extracting the date by hand is necessary!

6条回答
霸刀☆藐视天下
2楼-- · 2019-01-03 09:11

Grails Version >= 2.3

A setting in Config.groovy defines the date formats which will be used application-wide when binding params to a Date

grails.databinding.dateFormats = [
        'MMddyyyy', 'yyyy-MM-dd HH:mm:ss.S', "yyyy-MM-dd'T'hh:mm:ss'Z'"
]

The formats specified in grails.databinding.dateFormats will be attempted in the order in which they are included in the List.

You can override these application-wide formats for an individual command object using @BindingFormat

import org.grails.databinding.BindingFormat

class Person { 
    @BindingFormat('MMddyyyy') 
    Date birthDate 
}

Grails Version < 2.3

i can't and will not belief that extracting the date by hand is nessesary!

Your stubbornness is rewarded, it has been possible to bind a date directly since long before Grails 1.3. The steps are:

(1) Create a class that registers an editor for your date format

import org.springframework.beans.PropertyEditorRegistrar
import org.springframework.beans.PropertyEditorRegistry
import org.springframework.beans.propertyeditors.CustomDateEditor
import java.text.SimpleDateFormat

public class CustomDateEditorRegistrar implements PropertyEditorRegistrar {

    public void registerCustomEditors(PropertyEditorRegistry registry) {

        String dateFormat = 'yyyy/MM/dd'
        registry.registerCustomEditor(Date, new CustomDateEditor(new SimpleDateFormat(dateFormat), true))
    }
}

(2) Make Grails aware of this date editor by registering the following bean in grails-app/conf/spring/resources.groovy

beans = {
    customPropertyEditorRegistrar(CustomDateEditorRegistrar)
}

(3) Now when you send a date in a parameter named foo in the format yyyy/MM/dd it will automatically be bound to a property named foo using either:

myDomainObject.properties = params

or

new MyDomainClass(params)
查看更多
相关推荐>>
3楼-- · 2019-01-03 09:11

Grails 2.1.1 has new method in params for easy null safe parsing.

def val = params.date('myDate', 'dd-MM-yyyy')
// or a list for formats
def val = params.date('myDate', ['yyyy-MM-dd', 'yyyyMMdd', 'yyMMdd']) 
// or the format read from messages.properties via the key 'date.myDate.format'
def val = params.date('myDate')

Find it in doc here

查看更多
Juvenile、少年°
4楼-- · 2019-01-03 09:15

Grails Version >= 3.x

You can set in application.yml the date formats following this syntax:

grails:
  databinding:
    dateFormats:
      - 'dd/MM/yyyy'
      - 'dd/MM/yyyy HH:mm:ss'
      - 'yyyy-MM-dd HH:mm:ss.S'
      - "yyyy-MM-dd'T'hh:mm:ss'Z'"
      - "yyyy-MM-dd HH:mm:ss.S z"
      - "yyyy-MM-dd'T'HH:mm:ssX"
查看更多
该账号已被封号
5楼-- · 2019-01-03 09:20

Have you tried using any of the Grails date picker plugins?

Ive had good experiences with the calendar plugin.

(When using the calendar plugin) When you submit the request of the date selection you can automatically bind the query parameter to the domain object you want to populate with the request.

E.g.

new DomainObject(params)

You can also parse a "yyyy/MM/dd" date string like so...

new Date().parse("yyyy/MM/dd", "2010/03/18")
查看更多
Explosion°爆炸
6楼-- · 2019-01-03 09:32

Grails Version >= 2.3

A localeAware version to convert strings to date

In src/groovy:

package test

import org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequest
import org.grails.databinding.converters.ValueConverter
import org.springframework.context.MessageSource
import org.springframework.web.servlet.LocaleResolver

import javax.servlet.http.HttpServletRequest
import java.text.SimpleDateFormat

class StringToDateConverter implements ValueConverter {
    MessageSource messageSource
    LocaleResolver localeResolver

    @Override
    boolean canConvert(Object value) {
        return value instanceof String
    }

    @Override
    Object convert(Object value) {
        String format = messageSource.getMessage('default.date.format', null, "dd/MM/yyyy", getLocale())
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format)
        return simpleDateFormat.parse(value)
    }

    @Override
    Class<?> getTargetType() {
        return Date.class
    }

    protected Locale getLocale() {
        def locale
        def request = GrailsWebRequest.lookup()?.currentRequest
        if(request instanceof HttpServletRequest) {
            locale = localeResolver?.resolveLocale(request)
        }
        if(locale == null) {
            locale = Locale.default
        }
        return locale
    }
}

In conf/spring/resources.groovy:

beans = {
    defaultDateConverter(StringToDateConverter){
        messageSource = ref('messageSource')
        localeResolver = ref('localeResolver')
    }
}

The bean's name 'defaultDateConverter' is really important (to override the default date converter)

查看更多
Explosion°爆炸
7楼-- · 2019-01-03 09:34

@Don Thanks for the answer above.

Here's an alternative to the custom editor that checks first date time then date format.

Groovy, just add semi colons back in for java

import java.text.DateFormat
import java.text.ParseException
import org.springframework.util.StringUtils
import java.beans.PropertyEditorSupport

class CustomDateTimeEditor extends PropertyEditorSupport {
    private final java.text.DateFormat dateTimeFormat
    private final java.text.DateFormat dateFormat
    private final boolean allowEmpty

    public CustomDateTimeEditor(DateFormat dateTimeFormat, DateFormat dateFormat, boolean allowEmpty) {
        this.dateTimeFormat = dateTimeFormat
        this.dateFormat = dateFormat
        this.allowEmpty = allowEmpty
    }

    /**
     * Parse the Date from the given text, using the specified DateFormat.
     */
    public void setAsText(String   text) throws IllegalArgumentException   {
        if (this.allowEmpty && !StringUtils.hasText(text)) {
            // Treat empty String as null value.
            setValue(null)
        }
        else {
            try {
                setValue(this.dateTimeFormat.parse(text))
            }
            catch (ParseException dtex) {
                try {
                    setValue(this.dateFormat.parse(text))
                }
                catch ( ParseException dex ) {
                    throw new IllegalArgumentException  ("Could not parse date: " + dex.getMessage() + " " + dtex.getMessage() )
                }
            }
        }
    }

    /**
     * Format the Date as String, using the specified DateFormat.
     */
    public String   getAsText() {
        Date   value = (Date) getValue()
        return (value != null ? this.dateFormat.format(value) : "")
    }
}
查看更多
登录 后发表回答