Skip to main content

Grails - replacing g:datepicker with gui:datepicker

A typical datepicker code that is generated for your domain classes is shown below:

<g:datepicker name="dateOfJoin" value="${objInstance?.dateOfJoin}"
/>


Note: This code is autogenerated when you choose to create Controllers and Views by running the grails command "generate-all" for any domain class.

It displays the Date, Month, year drop downs. Also it shows Drop downs to select Hrs and Mins.



To remove the Hr and Mins dropdown a "precision" attribute should be used.

<g:datepicker name="dateOfJoin" value="${obj?.dateOfJoin}"
precision="day"/>




To enable Null dates in your domain object



The default datepicker options do not allow to choose a blank date.

By adding noSelection and default attributes as shown we can acheive the desired result.


<g:datepicker name="dateOfJoin" value="${objInstance?.dateOfJoin}"
default="none" noSelection="['':'-Choose-']"/>




More customization - Displaying fixed number of years in the dropdown box.



One more useful feature is customizing the years displayed in the years dropdown. By default this field displays +/- 100 years.

<g:datepicker name="dateOfJoin" value="${objInstance?.dateOfJoin}"
default="none" noSelection="['':'-Choose-']" years="${2005..2015}"/>

In case you donot want to hard code the years but dynamically generate the years from current year till next 5 years, we need to add the following.

<g:datepicker name="dateOfJoin" value="${objInstance?.dateOfJoin}"
default="none" noSelection="['':'-Choose-']" years="${(1900 + (new Date().year))..(1900+ (new Date() + (5 * 365)).year)}"/>

You could also choose to use Calendar class to get more accurate number of years and to avoid the logic of adding 1900 to the year.

Is it worth the effort when so much customization is needed.



A better alternative is to use the datepickers available from number of plugins available on grails plugin portal.

Remainder of this post is about the gui:datepicker from Grails plugin grails-ui


To start with we need to install grail-ui plugin.
Add the following to your head tag of the "create.gsp" or "edit.gsp" of the corresponding domain class you are working with.

<gui:resources components="['datePicker']"/>

Add class="yui-sam-skin" to the body tag of the page where you want to include the datepicker. It can also be added to the div tag that is sorrounding your form.

Replacing previous example with the following will give us editable textfield and a small calendar icon.

<gui:datePicker name="dateOfJoin" id="dateOfJoin" value="${objInstance?.dateOfJoin}">

It is important to put the id field same as your field in the domain class.



Additionally you can apply formatting to the date by using formatString attribute.
add formatString = "dd/MM/yyyy" to the tag.

Issues with gui:datepicker


When we try to save the data "Controller" object is unable to convert the parameter to the Date object. We need to apply a pre-processing logic before the "save" action is performed on the controller.

Add the following code to your controller. Note that format you used in datepicker should match the parse string that we are using.

def beforeInterceptor =
[ action:
{
params.dateOfJoin = params.dateOfJoin?Date.parse("dd/MM/yyyy", params.dateOfJoin):null


},
only:['save']
]
In case no date is selected dateOfJoin is set to null. The interceptor can be extended to another action by changing it to

def beforeInterceptor =
[ action:
{
params.dateOfJoin = params.dateOfJoin?Date.parse("dd/MM/yyyy", params.dateOfJoin):null


},
only:['save','update']
]

Caution: the date field should be declared to accept null values. In the domain class add the following
static constraints = {
dateOfJoin(nullable:true)
}

Comments

Popular posts from this blog

Grails - cross-field Date validation

Often we run into domain classes with date fields. If the domain class has two datefields, startDate and endDate, and the rule for a valid combination is "endDate to be greater than startDate", how do we handle? I listed below two of the options, either using domain level constraints or using the domain classes. Option 1: Using domain constraints. Let us take a sample Grails Domain class class Student{ String name String school Date startDate Date endDate } Add the following constraints to enforce validation rules where name, school, startDate cannot be blank and endDate if present should be greater than startDate.

Implementing advanced sort in Grails

The "list" pages generated by inbuilt scaffolding/template features of grails have pagination and sorting features. However, if the domain object displayed in the list is a nested object having another domain object as a property, you may notice that sort is not enabled for that field. Boiler plate code for the header of the list is shown below. As you would have noticed few columns have sortable columns automatically generated by Grails command, generate-all or generate-views. The properties 'partyAccount' and 'bankAccount' in this sample are domain classes nested in the domain class 'partyTransaction'. We could convert them to sortable columns by using the tag g:sortableColum...

CCAvenue and Magento Integration

India based e-commerce portals have to consider CCAvenue Payment Gateway as one of option for its simplicity and reliability. Magento e-commerce platform has several ready to use payment gateway plugins and a rich set of API to enhance its functionality to add new payment gateways that are not provided as part of its standard release. For one the projects we have to integrate Magento with CCavaenue. We browsed several forums for a free and ready to use plugin without much luck. Though there is no mention of any such plugin on CCAvenue website, we just tried calling the CCAvenue help desk and immediately we got an integration toolkit with detailed steps for integration. It works like a charm.