Form API

presentation by

19th August 2010

Examples in this presentation use Drupal 6.
Some knowledge of PHP required.

Form API is

The Drupal Form API provides sophisticated form techniques and also allows for almost unlimited possibilities for custom theming, validation, and execution of forms.

Form API Quickstart Guide

Not the same as Webform module

Features include

Form Structure

Form API structures depend on the standard PHP array

$form = array();

Element Properties & Attributes

Defined by indexes starting with a hash

Form API Reference

Child Elements

Defined by indexes starting without a hash

$form['address'] = array(); $form['address']['postal_address'] = array();

Why use Child Elements?

Types of Fields

1 of 3

2 of 3

3 of 3

Other modules can define their own element types
eg. date module

Form function variables

$form
Form structure
$form_state
The current state of the form
  • values
  • redirect
  • rebuild
  • storage
  • submitted
  • submit_handlers
  • validate_handlers
  • clicked_button
More info on $form_state
$form_id
The ID of the form—related to function name

Order of operations

When a form is submitted, all steps here are called

The form is built, data is passed in and validated, and then submitted

drupal_get_form

Prepares the form, caches content, validates elements.

Parameters:

Calling drupal_get_form

$menu_items['example/form/%'] = array( 'title' => 'Example Form', 'page callback' => 'drupal_get_form', 'page arguments' => array('example_test_form', 2) ); function example_show_form( $variable ) { return drupal_get_form('example_test_form', $variable); }

Form function

Builds the form and sets up functionality.

Parameters:

Returns:

Validate

Adds custom validation to the form.

Function name: function_name_validate

Parameters:

Submit

Form submission code run once the form is validated.

Function name: function_name_submit

Parameters:

Modifying existing forms

Use the form_alter hook

Function name: module_name_form_alter

Parameters:

Modifying existing forms: Example

function examplemodule_form_alter (&$form, &$form_state, $form_id){ if ($form_id == 'my_form'){ unset( $form['widget'] ); $form['gadget']['#type'] = 'hidden'; $form['thingamajig'] = array( '#type' => 'textfield', '#title' => t('Another field') ); $form['#submit'][] = 'examplemodule_update_thingamajig'; } }

More things you can do

Example: Invitation RSVP module

Data we require

Specification

rsvp.info

name = RSVP description = Lets users respond to an invitation package = Form API Demo version = 0.0 core = 6.x

rsvp.install

function rsvp_install(){ drupal_install_schema('rsvp'); } function rsvp_uninstall(){ drupal_uninstall_schema('rsvp'); } function rsvp_schema(){ $schema['rsvp_response'] = array( ... ); $schema['rsvp_response_person'] = array( ... ); return $schema; }

rsvp.module

function rsvp_menu(){ $items['rsvp/%node'] = array( 'title' => 'Respond to Invitation', 'page callback' => 'drupal_get_form', 'page arguments' => array('rsvp_response_form', 1), 'file' => 'rsvp.form.inc', 'module' => 'rsvp', 'access arguments' => array('respond to invitation') ); return $items; } function rsvp_perm(){ return array('respond to invitation'); }

rsvp.form.inc

function rsvp_response_form(&$form_state, $event_node) { return $form; } function rsvp_response_form_validate($form, &$form_state) { } function rsvp_response_form_submit(&$form, &$form_state) { }

rsvp.form.inc: rsvp_response_form

1 of 6

$form['event_node'] = array( '#type' => 'value', '#value' => $event_node ); $form['invitee'] = array( '#tree' => TRUE, '#type' => 'fieldset', '#title' => 'Enter your details', '#collapsible' => FALSE );

rsvp.form.inc: rsvp_response_form

2 of 6

$form['invitee']['formal_name'] = array( '#type' => 'textfield', '#title' => t("Name"), '#description' => t("What your parents named you, what the government calls you."), '#required' => TRUE, '#maxlength' => 127 ); $form['invitee']['informal_name'] = array( '#type' => 'textfield', '#title' => t("Nickname"), '#description' => t("What your friends call you."), '#maxlength' => 127 );

rsvp.form.inc: rsvp_response_form

3 of 6

$form['invitee']['gender'] = array( '#type' => 'radios', '#title' => t('Gender'), '#options' => array( t("Male"), t("Female"), t("Not telling"), ), '#required' => TRUE );

rsvp.form.inc: rsvp_response_form

4 of 6

$form['invitee']['diet'] = array( '#type' => 'textarea', '#title' => t("Dietary Requirements/Preferences"), '#description' => t("If you have any allergies or dietary preferences, ". "note them here to ensure we cater well for you.") ); $form['invitee']['access'] = array( '#type' => 'textarea', '#title' => t("Access Requirements"), '#description' => t("If you have any disabilities or access issues, ". "note them here to ensure ". "you receive the assistance you need.") );

rsvp.form.inc: rsvp_response_form

5 of 6

$form['ticket'] = array( '#type' => 'select', '#required' => TRUE, '#title' => t("How do you want to receive your tickets?"), '#options' => _rsvp_ticket_options() ); $form['email'] = array( '#type' => 'textfield', '#title' => t("Email"), '#maxlength' => 255 );

rsvp.form.inc: rsvp_response_form

6 of 6

$form['address'] = array( '#type' => 'textarea', '#title' => t("Postal Address") ); $form['submit'] = array( '#type' => 'submit', '#value' => t("Submit RSVP") ); return $form;

rsvp.form.inc: _rsvp_ticket_options

return array( t("At the door"), t("Via email"), t("In the mail") );

rsvp.form.inc: rsvp_response_form_validate

1 of 3

$values = $form_state['values']; if ($values['event_node']->type != 'event'){ form_set_error('event_node', "This is not a valid event. ". "Please check the URL you received and try again."); }

rsvp.form.inc: rsvp_response_form_validate

2 of 3

$ticket_opts = _rsvp_ticket_options(); if( $ticket_opts[ $values['ticket'] ] == "Via email" ) { if( $values['email'] == '' ) form_set_error( 'email', "If you want to receive ". "your ticket by email, please specify an email address." ); else { if( !valid_email_address($values['email'])) form_set_error( 'email', "Please specify a valid ". "email address." ); } }

rsvp.form.inc: rsvp_response_form_validate

3 of 3

if( $ticket_opts[ $values['ticket'] ] == "In the mail" ) { if( $values['address'] == '' ) form_set_error( 'address', "If you want to receive ". "your ticket by mail, please specify a postal address." ); }

rsvp.form.inc: rsvp_response_form_submit

1 of 5

$values = $form_state['values']; if( $values['op'] == 'Submit RSVP' ){ $response_fields = array( 'event_nid' => $values['event_node']->nid, 'ticket' => $values['ticket'], 'email' => $values['email'], 'address' => $values['address'] ); $response_placeholders = array( 'event_nid' => '%d', 'ticket' => "'%s'", 'email' => "'%s'", 'address' => "'%s'" );

rsvp.form.inc: rsvp_response_form_submit

2 of 5

$success = db_query('INSERT INTO {rsvp_response} ('. implode(', ', array_keys($response_fields)) . ') VALUES ('. implode(', ', array_values( $response_placeholders )). ')', array_values( $response_fields )); if (!$success) { return; } $response_id = db_last_insert_id('rsvp_response', 'response_id');

rsvp.form.inc: rsvp_response_form_submit

3 of 5

$person_fields = array( 'response_id' => $response_id, 'is_guest' => 0, 'formal_name' => $values['invitee']['formal_name'], 'informal_name' => $values['invitee']['informal_name'], 'gender' => $values['invitee']['gender'], 'diet' => $values['invitee']['diet'], 'access' => $values['invitee']['access'] );

rsvp.form.inc: rsvp_response_form_submit

4 of 5

$person_placeholders = array( 'response_id' => '%d', 'is_guest' => '%d', 'formal_name' => "'%s'", 'informal_name' => "'%s'", 'gender' => "'%s'", 'diet' => "'%s'", 'access' => "'%s'" );

rsvp.form.inc: rsvp_response_form_submit

5 of 5

$success = db_query('INSERT INTO {rsvp_response_person} ('. implode(', ', array_keys($person_fields)) . ') VALUES ('. implode(', ', array_values( $person_placeholders )). ')', array_values( $person_fields )); drupal_set_message("Thanks for responding to this RSVP!"); drupal_goto('node/'.$values['event_node']->nid); }

The End