Drupal and the #date
Recent projects have led me into heavy use of the Drupal 6.x Form API. As powerful and wonderful as it is, I occasionally run into an issue that is not easily solved. This is an account of my struggle with the #date type field.
For those unfamiliar with the Drupal Form API, it is an engine within the Drupal CMS that essentially converts a set of arrays into form fields and controls. That may be a little simplified but if you want to learn more about it see this.
The Form API (FAPI) provides a convenient type called #date which draws three select elements to the page. One each for Day, Month and Year. Since dates are often collected on forms having something this simple makes sense.
I ran into problems when I realized that I could not set the default values of these selects to nothing or blank. My client wanted their users to see empty values in the fields prompting them to choose the correct values.
When setting the default values to an empty string, #date defaults to Jan 01, 1900. Since I needed blank initial values, I was off to do some overriding (hacking the core is a no-no).
What Was Needed:
- Date fields that had blank initial values.
- Date fields needed to be validated against blank values. (Invalid dates was considered but not included)
The Fix:
The first step is to create a date field in your set of form arrays.
Initial Date Field
$form = array();
$form['dob'] = array(
'#type' => 'date',
'#title' => t('Birthdate'),
'#default_value' => array('year' => '','month' => '','day' => ''),
'#required' => true,
);
The above will draw three select elements to the page titled "Birthdate" with initial values of Jan 01, 1900. Had we not specified the #default_value, the initial values would have been the current date.
We need to override what Drupal wants to use for values in those fields. This can be accomplished using the #after_build attribute and setting it's callback to your own function.
'#after_build' => array('my_date_callback');The callback looked like this:
function my_date_callback($form_element, $form_values){
$aTmp = array('' => '--');
$form_element['day']['#options'] = $aTmp + drupal_map_assoc(range(1, 31));
$form_element['month']['#options'] = $aTmp + drupal_map_assoc(range(1, 12), 'map_month');
$form_element['year']['#options'] = $aTmp + drupal_map_assoc(range(1900, 2050));
return $form_element;
}
After adding the attribute and the callback function, the date fields now have initial values of "--" with a value set to nothing.
There is one gotcha here. Drupal will try to validate the date on submit. To allow blank dates to pass validation, the date_validate function must be overridden. PHP will not allow the function to be redefined, so Drupal must be told to use a different validation function. This is done by adding the #element_validate attribute and having it call a custom validation function.
#element_validate => array('mymodule_date_validate');Add the validation function:
function mymodule_date_validate($form) {
//do whatever you need to here, doing nothing simply passes everything through.
}
With these attributes and functions in place, the date fields will initially be blank and pass Drupal validation upon submit.
Final Date Field and Callbacks
$form = array();
$form['dob'] = array(
'#type' => 'date',
'#title' => t('Birthdate'),
'#default_value' => array('year' => '','month' => '','day' => ''),
'#required' => true,
'#after_build' => array('my_date_callback'),
'#element_validate' => array('mymodule_date_validate')
);
function my_date_callback($form_element, $form_values){
$aTmp = array('' => '--');
$form_element['day']['#options'] = $aTmp + drupal_map_assoc(range(1, 31));
$form_element['month']['#options'] = $aTmp + drupal_map_assoc(range(1, 12), 'map_month');
$form_element['year']['#options'] = $aTmp + drupal_map_assoc(range(1900, 2050));
return $form_element;
}
function mymodule_date_validate($form) {
//do whatever you need to here, doing nothing simply passes everything through.
}
To get the desired outcome, this all seemed like a great deal of work. But most of it was hunting down all the bits and pieces to get there. Hopefully this will help someone else out there get their date to do what they want.
Cheers
-nash
- jimmynash's blog
- Login to post comments
