views:

321

answers:

1

Hey folks,

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?

Thanks for your help, Jan

+1  A: 

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.

 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.

Scott Warren
This looks very cool; is this the recommended way to implement progressive enhancement with Grails?
Alison
Not sure what you mean by "progressive enhancement" but I like it because it leaves Grails as is and works well. It also degrades very well so it should work.
Scott Warren
Progressive enhancement ~= graceful degradation (http://en.wikipedia.org/wiki/Progressive_enhancement)
Alison
Thanks, I learnt something. I guess this is ONE way to implement progressive enhancement with Grails
Scott Warren