Tech Blog :: Customizing Drupal date field with hook_form_alter and #after_build


Jul 30 '10 7:57pm
Tags

Customizing Drupal date field with hook_form_alter and #after_build

I spent a long time today trying to figure out how to customize a Date field in Drupal 6. The field is called field_recurring_dates and looked like this:

I wanted the "To" date to only show the time, no date - so the field has Date, Start Time, and End Time. The field is repeating/"unlimited" so the whole unit gets returned via AHAH with the "Add Another Item" button. Renaming that to "Add another day" was easy, but getting the date/time fields to change was elusive. I tried everything else I could think of: #process, theme overrides for every element, preprocess, with no luck. The field is generated by a hook_elements inside the Date module, and I couldn't find the equivalent of a hook_elements_alter ... until I asked on IRC and got the perfect solution from Fox: the Form API's #after_build callback.

So here's the code, finally working, inside a custom module:

function MODULE_form_alter(&$form, $form_state, $form_id) {
  // work on initial node form and AHAH-generated partial form
  if ($form['#id'] == 'node-form' || $form_id == 'content_add_more_js') {
    if (isset($form['field_recurring_dates'])) {
      $form['field_recurring_dates']['#after_build'][] = 'custom_date_combo_after_build';
    }
 
    // rename the 'Add' button
    if (isset($form['field_recurring_dates']['field_recurring_dates_add_more'])) {
      $form['field_recurring_dates']['field_recurring_dates_add_more']['#value'] = 'Add Another Day';
    }
 
  }
}
 
function custom_date_combo_after_build(&$element) {
  // can be MULTIPLE items
  // need to find all the NUMERICALLY-KEYED elements
  foreach($element as $key => &$field) {
    if (is_numeric($key) && is_array($field) && isset($field['value']) && isset($field['value2'])) {
      // remove the Date part of 'To Date's
      unset($field['value2']['date']);
 
      // rename 'From Date' => 'Date'
      $field['value']['#title'] = 'Date';
 
      $field['value']['time']['#title'] = 'From Time';
      $field['value2']['time']['#title'] = 'To Time';
 
      // remove 'To date' block title
      $field['value2']['#title'] = '';
 
      // only need helper text outside whole group
      unset($field['#fieldset_description']);   
    }
  }
  return $element;
}

With a little CSS, it now looks like this:

Perfect!

Update and Correction: The above line,
unset($field['value2']['date']);
didn't work, because the missing 2nd date field messed up the field's validation.

So I checked out the Date Single Day module mentioned in the comments, and it's pretty much identical to this method except for this change:
$field['value2']['date']['#type'] = 'hidden';   // not unset()!

That seems to work well.
As a side note, I tried the #date_format attribute mentioned in the comments and couldn't get that to work at all. Also the first and second dates aren't separated in the form array enough to set a different #date_format on each. So #after_build seems to be the best bet.

The trick is the '#date_format' property of the field. The date module automatically figures out whether to show the date, time, or date and time fields based on whether the '#date_format' property includes date and/or time indicators. So probably all you had to do was this:


function MYMODULE_form_alter(&$form, $form_state, $form_id) {
if ($form['#id'] == 'node-form' || $form_id == 'content_add_more_js') {
foreach ($form['field_recurring_dates'] as $key => &$field) {
if (is_numeric($key) && is_array($field)) {
$field['#date_format'] = 'H:i';
}
}
}

Here you find an existing module that does the same:
http://drupal.org/project/date_single_day

Nice to see a selection of options to achieve the same effect!

The #after_build property could be used in many cases, so good to see a real world example of it in action.

Very cool. It looks like date_single_day uses the same #after_build method, but I'll keep #date_format in mind for the future!

Thanks for all the comments guys, I added an update and correction to the post which relates to them.
- Ben

yea! i love good things. i'll keep sending out good vibes for the apartment to sell! :-) hentaiube [url="http://www.vishuis.co.za/cartoon"]hentaiube[/url] http://www.vishuis.co.za/cartoon hentaiube tarahentai [url="http://abigames.com/girl"]tarahentai[/url] http://abigames.com/girl tarahentai tetrahentai [url="http://www.sitedoadvogado.com.br/cartoon"]tetrahentai[/url] http://www.sitedoadvogado.com.br/cartoon tetrahentai

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <blockquote>
  • Lines and paragraphs break automatically.
  • Identifies Twitpic URLs, downloads their images, displays image instead of URL.

More information about formatting options