Grails Date Property Editor

2019-03-22 07:02发布

i'm using the jQuery UI datepicker instead of the <g:datePicker>, which is changing the selected date in a textbox. Now I want to save this neatly back into my database, and came across custom property editors. click me hard to see the topic on StackOverflow

However, adding this custom PropertyEditor didn't change anything, dates are still displayed like '2010-01-01 00:00:00.0' and if I try to save a date it crashes with Cannot cast object '05.05.2010' with class 'java.lang.String' to class 'java.util.Date'.

Is there any additional magic needed, like a special naming of the textbox or something like that?

3条回答
冷血范
2楼-- · 2019-03-22 07:46

There shouldn't be that much magic.

resources.groovy

beans = {
    customPropertyEditorRegistrar(CustomPropertyEditorRegistrar)
}

src/groovy/{yourpackage}/CustomPropertyEditorRegistrar.groovy

class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar {
    @Override
    void registerCustomEditors(PropertyEditorRegistry registry) {
        // Always set the nullable to true and handle not nullable fields through constraints
        registry.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("dd.MM.yyyy"), true));
    }
}
查看更多
smile是对你的礼貌
3楼-- · 2019-03-22 07:59

You many need to check the GrailsBinder code. However I have a possibly simpler solution. Below is some JQuery Code which finds all the g:datePicker code and renders a Grails Date Picker. It hides the original Select Boxes (so this code will degrade gracefully) then insert a new Textbox and the JQuery UI Datepicker. This solution also works when the user changes just the Text box without dropping down the date picker.

 function updateDatePicker () { 
    $("input[value='date.struct']:hidden").each(function() {
        var dateFormat = "dd/mm/yy";
        var name = $(this).attr('name');            
        var id = name.replace(".", "_").replace("[", "_").replace("]", "_") + "_input"; // Create JQuery Friendly ID

        if ($('#'+id).length == 0) {

            // Find the Select Elements
            var selectDay= $(this).nextAll("select:eq(0)").hide();
            var selectMonth = $(this).nextAll("select:eq(1)").hide();
            var selectYear = $(this).nextAll("select:eq(2)").hide();

            // Get the Values
            var dateDay= $(selectDay).val();
            var dateMonth = $(selectMonth).val();
            var dateYear = $(selectYear).val();

            // Calculate the Current Input Value
            var val = "";           
            if (dateDay != "" && dateYear != "" && dateMonth != "") { // If there is a date in the Selects then use it otherwise it's empty
                var date = new Date (dateYear, dateMonth-1, dateDay);
                val = $.datepicker.formatDate(dateFormat, date);
            }

            // Create element
            var template = "<input type='text' name='"+ id +"' id='"+ id +"' value='"+ val +"'/>";

            if ($(this).parent(".datePickerCalenderView").size()) {
                template = "<div id='"+ id +"'/>";
            }


            $(this).before(template);       
            var displayWidget = $('#' + id );

            displayWidget.blur(function() {         
                var date = $.datepicker.parseDate(dateFormat, $(this).val());

                if (date == null) {
                    $(selectDay).val("");
                    $(selectMonth).val("");
                    $(selectYear).val("");
                }
                else {
                    $(selectDay).val(date.getDate());
                    $(selectMonth).val(date.getMonth()+1);
                    $(selectYear).val(date.getFullYear());
                }
            }).keydown(function(event) {
                // Show popup on Down Arrow
                if (event.keyCode == 40) {
                    displayWidget.datepicker("show");
                }
            });

            displayWidget.datepicker({  
                changeMonth: true,
                changeYear: true,
                dateFormat: dateFormat,
                constrainInput: true,           
                showButtonPanel: true,
                showWeeks: true,
                showOn: 'button',           
                onSelect: function(dateText, inst) { 
                    if (inst == null) {
                        $(selectDay).val("");
                        $(selectMonth).val("");
                        $(selectYear).val("");
                    }
                    else {
                        $(selectDay).val(inst.selectedDay);
                        $(selectMonth).val(inst.selectedMonth+1);
                        $(selectYear).val(inst.selectedYear);
                    }
                }           
            });     
        }
    });   
}

Finally add this code to update the inputs when the page loads and when an AJAX call is made

$(document).ready (function (){ 
    updateDatePicker();

    $("#spinner").ajaxComplete (function(event, request, settings){   
        updateDatePicker();
    });
});

Hope this helps.

查看更多
唯我独甜
4楼-- · 2019-03-22 08:03

I have a created a simple grails custom tag to use the jQuery UI datepicker. It's characteristics are as follows:

  1. It creates three hidden input fields dateField_day, dateField_month, dateField_year

  2. It's responsible for populating these hidden input fields when a date has been selected from the calendar.

  3. Supports having multiple date fields without any conflict.

It's prerequisites are as follows:

  1. You have to have jquery installed and configured properly in your app structure. That is all the js, css, and themes

The taglib code is as follows:

class JqueryDatePickerTagLib {

def jqDatePicker = {attrs, body -> def out = out def name = attrs.name def id = attrs.id ?: name

//Create date text field and supporting hidden text fields need by grails
out.println "<input type=\"text\" name=\"${name}\" id=\"${id}\" />"
out.println "<input type=\"hidden\" name=\"${name}_day\" id=\"${id}_day\" />"
out.println "<input type=\"hidden\" name=\"${name}_month\" id=\"${id}_month\" />"
out.println "<input type=\"hidden\" name=\"${name}_year\" id=\"${id}_year\" />"

//Code to parse selected date into hidden fields required by grails
out.println "<script type=\"text/javascript\"> \$(document).ready(function(){"
out.println "\$(\"#${name}\").datepicker({"
out.println "onClose: function(dateText, inst) {"
out.println "\$(\"#${name}_month\").attr(\"value\",new Date(dateText).getMonth() +1);"
out.println "\$(\"#${name}_day\").attr(\"value\",new Date(dateText).getDate());"
out.println "\$(\"#${name}_year\").attr(\"value\",new Date(dateText).getFullYear());"
out.println "}"
out.println "});"
out.println "})</script>"

} }

The gsp code is as follows:

<g:jqDatePicker name="orderDate"/>

You can find the full article at: My Blog

查看更多
登录 后发表回答