
Drupal Form Elements
Sometime we require from elements for filling “Height” or “Credit card expiry date” or “Phone number(in any specific format)”. We can easily create these type of form elements in Drupal. I am showing here how we can create such type of form elements.
Here I am taking the example of “Height” element. For height element we require two select boxes. One for showing feet and other for inches.
Step 1: First create “hook_elements()” in your module. This hook allows modules to declare their own Forms API element types and specify their default values.
function module_name_elements() { return array( 'height' => array( '#input' => TRUE, '#process' => array('expand_height'), '#element_validate' => array('height_validate'), ), }
Step 2: Define the “#process” callback function “expand_height()”. This will take $element as argument and process it.
function expand_height($element) { // Assigning default values to element. You can override these values by passing your own values using "#default_value". if (empty($element['#value'])) { $element['#value'] = array( 'feet' => '-', 'inch' => '-', ); } $element['#tree'] = TRUE; $parents = $element['#parents']; $parents[] = 'feet'; $element['feet'] = array( '#type' => 'select', '#default_value' => $element['#value']['feet'], '#options' => array('-' => '-', '2' => '2', '3' => '3', '4' => '4', '5' => '5', '6' => '6', '7' => '7', '8' => '8',), '#suffix' => t('ft.'), ); $parents = $element['#parents']; $parents[] = 'inch'; $element['inch'] = array( '#type' => 'select', '#default_value' => $element['#value']['inch'], '#options' => array('-' => '-', '0' => '0', '1' => '1', '2' => '2', '3' => '3', '4' => '4', '5' => '5', '6' => '6', '7' => '7', '8' => '8', '9' => '9', '10' => '10', '11' => '11'), '#suffix' => t('in.'), ); return $element; }
Step 3: Theme your custom element by defining “theme_hook()” for your element.
function theme_height($element) { return theme('form_element', $element, '<div class="container-inline">'. $element['#children'] .'</div>'); }
step 4: We need to register our above theme function “theme_height()” in theme registry. We can do that using “hook_theme()” hook. To see effect of your code, clear your cache because all theme hook is cached by Drupal.
function module_name_theme() { return array( 'height' => array( 'arguments' => array('element' => NULL)) ); }
Step 5: Define “hook_validate()” for your element. This function is automatically called by FORM API and it validate the given value of element. We verify the values of element and if value is not valid we will set error message using form_error() function. This function take $element as argument.
function height_validate($element) { if (trim($element['#value']['feet']) == '-' || trim($element['#value']['inch']) == '-') { form_error($element, t('The specified height is invalid.')); } }
How you use it:
$user->height = array('feet' => '5', 'inch' => '8'); // Create element of 'type' height $form['height'] = array('#type' => 'height', '#title' => t('Height'), '#required' => TRUE, '#default_value' => isset($user->height) ? $user->height : array('feet' => '-', 'inch' => '-'), ); //Access it in form_submit() like this $height = $edit['height']['feet']. '-' . $edit['height']['inch'];
Code for Phone Number Element
<php function mymodule_theme() { return array( 'phone' => array( 'arguments' => array('element' => NULL)) ); } function mymodule_elements() { return array( 'phone' => array( '#input' => TRUE, '#process' => array('expand_phone'), '#element_validate' => array('phone_validate'), ), ); } function expand_phone($element) { if (empty($element['#value'])) { $element['#value'] = array( 'part1' => '', 'part2' => '', 'part3' => '', ); } $element['#tree'] = TRUE; $parents = $element['#parents']; $parents[] = 'part1'; $element['part1'] = array( '#type' => 'textfield', '#size' => 4, '#maxlength' => 3, '#default_value' => $element['#value']['part1'], '#prefix' => '(', '#suffix' => ')', ); $parents = $element['#parents']; $parents[] = 'part2'; $element['part2'] = array( '#type' => 'textfield', '#size' => 4, '#maxlength' => 3, '#default_value' => $element['#value']['part2'], '#suffix' => '-', ); $parents = $element['#parents']; $parents[] = 'part3'; $element['part3'] = array( '#type' => 'textfield', '#size' => 6, '#maxlength' => 4, '#default_value' => $element['#value']['part3'], ); return $element; } function theme_phone($element) { return theme('form_element', $element, '<div class="container-inline">'. $element['#children'] .'</div>'); } function phone_validate($element) { if (trim($element['#value']['part1']) == '' || trim($element['#value']['part2']) == '' || trim($element['#value']['part3']) == '' || !is_numeric($element['#value']['part1']) || !is_numeric($element['#value']['part2']) || !is_numeric($element['#value']['part3'])) { form_error($element, t('The specified phone number is invalid.')); } } ?>
Code for Credit card expiry date Element
<?php function mymodule_theme() { return array( 'cardexpdate' => array( 'arguments' => array('element' => NULL)) ); } function mymodule_elements() { return array( 'cardexpdate' => array( '#input' => TRUE, '#process' => array('expand_cardexpdate'), '#element_validate' => array('cardexpdate_validate'), ), ); } function expand_cardexpdate($element) { $next_month_date = strtotime("+1 month"); $month = date('n', $next_month_date); $year = date('Y', $next_month_date); if (empty($element['#value'])) { $element['#value'] = array( 'month' => $month, 'year' => $year, ); } $element['#tree'] = TRUE; $parents = $element['#parents']; $parents[] = 'month'; $element['month'] = array( '#type' => 'select', '#default_value' => $element['#value']['month'], '#options' => drupal_map_assoc(range(1, 12), 'cardexpdate_map_month'), ); $parents = $element['#parents']; $parents[] = 'year'; $element['year'] = array( '#type' => 'select', '#default_value' => $element['#value']['year'], '#options' => drupal_map_assoc(range($year, 2020)), ); return $element; } function theme_cardexpdate($element) { return theme('form_element', $element, '<div class="container-inline">'. $element['#children'] .'</div>'); } function cardexpdate_validate($element) { $month = $element['#value']['month']; $year = $element['#value']['year']; $exp_date = mktime(0, 0, 0, $month, date('j'), $year); if ($exp_date < time()) { form_error($element, t('The specified expiry date is invalid.')); } } function cardexpdate_map_month($month) { return format_date(gmmktime(0, 0, 0, $month, 2, 1970), 'custom', 'm', 0); } ?>
#1 by Aman - September 25th, 2009 at 10:39
Thats wonderful. I was searching for this since a long time. Thanks buddy, you made my day.
#2 by AB - November 2nd, 2009 at 15:21
Thanks for the good tutorial. This is useful for every one.
I am trying to create a custom form element for Drupal 6 Form API. In Process function, I wrote http://pastebin.com/f4d784832. But this is changing the ID of the element to <>-my-input and Name is changing to <>[my_input]. How do I prevent that?
Also, Can you explain the purpose of:
$parents = $element['#parents'];
$parents[] = ‘part2′;
$element['part2'] = array(
…
);
Can’t we use (When I tried, it is returning some errors):
$element = array(
…
);
#3 by Alexey - August 10th, 2011 at 18:54
Hello! I have a problem.
I tried to do these three examples in Drupal 7 but got nothing. No errors, no output at all. What’s wrong?
#4 by chris - September 23rd, 2011 at 02:57
Regarding D7, you now pass ‘variables’ instead. Try modifying the code:
function mymodule_theme() {
return array(
‘cardexpdate’ => array(
‘variables’ => array(‘element’ => NULL))
);
}
#5 by Floris - November 19th, 2011 at 04:03
This theme with D7 not work.. The theme type form_element not exist.. how can fix this problem?