This is an example demonstrating how a module can define custom form elements.
Form elements are already familiar to anyone who uses Forms API. Examples of core form elements are 'textfield', 'checkbox' and 'fieldset'. Drupal utilizes hook_elements() to define these FAPI types, and this occurs in the core function system_elements().
Each form element has a #type value that determines how it's treated by the Form API and how it's ultimately rendered into HTML. hook_elements() allows modules to define new element types, and tell the Form API what default values they should automatically be populated with.
By implementing hook_elements in your own module, you can create custom form elements with their own properties, validation and theming.
In this example, we will define a phone number field that is expanded into several text fields for area code, phone number and extention, each of which is validated.
Functions & methods
| Name | Description |
|---|---|
| example_element_demo | This is a simple form to demonstrate how to use the phonenumber form element we defined. |
| example_element_elements | Implementation of hook_elements(). |
| example_element_expand | Our process callback to expand the control. |
| example_element_menu | Implementation of hook_menu(). |
| example_element_validate | Our element's validation function. |
| theme_phonenumber | Theme function to format the output. |
File
developer/examples/example_element.module- <?php
-
-
- /**
- * @file
- * This is an example demonstrating how a module can define custom form
- * elements.
- *
- * Form elements are already familiar to anyone who uses Forms API. Examples
- * of core form elements are 'textfield', 'checkbox' and 'fieldset'. Drupal
- * utilizes hook_elements() to define these FAPI types, and this occurs in
- * the core function system_elements().
- *
- * Each form element has a #type value that determines how it's treated by
- * the Form API and how it's ultimately rendered into HTML. hook_elements()
- * allows modules to define new element types, and tell the Form API what
- * default values they should automatically be populated with.
- *
- * By implementing hook_elements in your own module, you can create custom
- * form elements with their own properties, validation and theming.
- *
- * In this example, we will define a phone number field that is expanded
- * into several text fields for area code, phone number and extention, each
- * of which is validated.
- */
-
- /**
- * Implementation of hook_menu().
- *
- * This just defines a page that we can use to test our form elements.
- */
- function example_element_menu($may_cache) {
- $items = array();
- if ($may_cache) {
- $items[] = array(
- 'path' => 'example_element',
- 'title' => t('Example element demo'),
- 'access' => user_access('access content'),
- 'type' => MENU_NORMAL_ITEM,
- 'callback' => 'drupal_get_form',
- 'callback arguments' => array('example_element_demo'),
- );
- }
- return $items;
- }
-
- /**
- * Implementation of hook_elements().
- */
- function example_element_elements() {
- $type['phonenumber'] = array(
- '#input' => TRUE,
- '#process' => array('example_element_expand' => array()),
- '#validate' => array('example_element_validate' => array()),
- '#default_value' => array('areacode' => '', 'number' => '', 'extension' => ''),
- );
-
- return $type;
- }
-
- /**
- * Our process callback to expand the control.
- */
- function example_element_expand($element) {
- $element['#tree'] = TRUE;
-
- if (!isset($element['#value'])) {
- $element['#value'] = array('areacode' => '', 'number' => '', 'extension' => '');
- }
-
- $element['areacode'] = array(
- '#type' => 'textfield',
- '#size' => 3,
- '#maxlength' => 3,
- '#value' => $element['#value']['areacode'],
- '#prefix' => '(',
- '#suffix' => ')',
- );
- $element['number'] = array(
- '#type' => 'textfield',
- '#size' => 8,
- '#maxlength' => 8,
- '#required' => TRUE,
- '#value' => $element['#value']['number'],
- );
- $element['extension'] = array(
- '#type' => 'textfield',
- '#size' => 10,
- '#maxlength' => 10,
- '#prefix' => t('ext'),
- '#value' => $element['#value']['extension'],
- );
-
- return $element;
- }
-
- /**
- * Our element's validation function.
- *
- * We check that:
- * - the area code is a three digit number
- * - the number is numeric, with an optional dash
- *
- * Any problems are attached to the form element using form_error().
- */
- function example_element_validate($form) {
- if (isset($form['#value']['areacode'])) {
- if (0 == preg_match('/^\d{3}$/', $form['#value']['areacode'])) {
- form_error($form['areacode'], t('The areacode is invalid.'));
- }
- }
- if (isset($form['#value']['number'])) {
- if (0 == preg_match('/^\d{3}-?\d{4}$/', $form['#value']['number'])) {
- form_error($form['number'], t('The number is invalid.'));
- }
- }
- return $form;
-
- }
-
- /**
- * Theme function to format the output.
- *
- * We use the container-inline class so that all three of the HTML elements
- * are placed next to each other, rather than on separate lines.
- */
- function theme_phonenumber($element) {
- return theme('form_element', $element, '<div class="container-inline">'. $element['#children'] .'</div>');
- }
-
- /**
- * This is a simple form to demonstrate how to use the phonenumber form
- * element we defined.
- */
- function example_element_demo() {
- $form['example_element_test_1'] = array(
- '#type' => 'phonenumber',
- '#title' => t('Phone number 1'),
- '#default_value' => variable_get('example_element_test_1',
- array('areacode' => '123', 'number' => '456-7890', 'extension' => '')
- ),
- '#description' => t('A phone number.'),
- );
-
- $form['example_element_test_2'] = array(
- '#type' => 'phonenumber',
- '#title' => t('Phone number 2'),
- '#default_value' => variable_get('example_element_test_2',
- array('areacode' => '', 'number' => '456-7890', 'extension' => '23')
- ),
- '#description' => t('Another phone number, a fax perhaps?'),
- );
-
- return system_settings_form($form);
- }
-