Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The Incredible Form API

The Incredible Form API

An introduction to the Drupal Form API for developers new to Drupal. Explains the basic workflow of a form, reasoning for having the Form API and the basics of creating, validating and submitting your own form and altering the form's provided by other modules.

eojthebrave

May 19, 2012
Tweet

More Decks by eojthebrave

Other Decks in Technology

Transcript

  1. <form> <label for="select">Hero:</label><br/> <select name="hero"> <option value="sman">Super-Man</option> <option value="hulk">Hulk</option> <option

    value="joe">The Joe!</option> </select> <br/> <label for="other">Other:</label><br/> <input type="textfield" name="other"/> </form> efore Drupal forms there where HTML forms ... B In the mean time some crafty drupal developers holed up in a hotel room and emerged days later ... Saturday, May 19, 12
  2. HTML forms are ... those html forms however ... sub-optimal!

    • Vulnerable to local modification • Hard to make secure • Cumbersome to update • Have to write complex code to parse incoming data in to a meaningful format Saturday, May 19, 12
  3. http://example.com/contact I’m on it! Let me find the module that

    will build that form for you. Saturday, May 19, 12
  4. And with a little extra effort .... Ugh! Okay ...

    okay. Just let me display this form again and we’ll get those errors corrected. ERROR! $_POST Saturday, May 19, 12
  5. “$_POST” ? Okay, lets try this again. Holy smokes. It

    actually worked that time. Now what? Saturday, May 19, 12
  6. reviously ... P • Call drupal_get_form() • Your module returns

    a $form array • If there is $_POST data, validate! • If there are errors redisplay the form and highlight! • No errors? Submit the form! • Redirect or display the form again but empty. Saturday, May 19, 12
  7. hy Drupal forms rule ... W • Automatic workfloW •

    Automatic security • Consistent HTML output • Ability to inject custom behaviors • Easily encapsulate complex logic in to reusable elements. (File upload, Five Star) Saturday, May 19, 12
  8. <?php $form = array(); $form['element'] = array( '#property' => 'value',

    '#property_2' => 'value', 'sub_element' => array( '#sub_element_property' => 'value', ... ); ); $form['name'] = array( '#type' => 'textfield', '#title' => t('Name'), '#default_value' => $user->name, '#required' => TRUE, ); ‘elements’ and #properties are the basis of all forms ... Saturday, May 19, 12
  9. <?php $form = array(); $form['element'] = array( '#property' => 'value',

    '#property_2' => 'value', 'sub_element' => array( '#sub_element_property' => 'value', ... ); ); $form['name'] = array( '#type' => 'textfield', '#title' => t('Name'), '#default_value' => $user->name, '#required' => TRUE, ); ‘elements’ and #properties are the basis of all forms ... Properties always start with a # anything that doesn’t is treated as an element. Saturday, May 19, 12
  10. <?php $form = array(); $form['element'] = array( '#property' => 'value',

    '#property_2' => 'value', 'sub_element' => array( '#sub_element_property' => 'value', ... ); ); $form['name'] = array( '#type' => 'textfield', '#title' => t('Name'), '#default_value' => $user->name, '#required' => TRUE, ); ‘elements’ and #properties are the basis of all forms ... Properties always start with a # anything that doesn’t is treated as an element. Saturday, May 19, 12
  11. Not all #properties work the same ... $form['name'] = array(

    '#type' => 'textfield', '#title' => t('Name'), '#default_value' => $user->name, '#required' => TRUE, '#element_validate' => array('callback_function_name'), ); function callback_function_name($element, &$form_state, $form) { // That's not a name, ERROR! } Saturday, May 19, 12
  12. Making Complex UX easy ... $form['pet_type'] = array( '#type' =>

    'radios', '#options' => drupal_map_assoc(array(t('Cat'), t('Unicorn'))), '#title' => t('What type of pet do you have?') ); $form['unicorn_horns'] = array( '#type' => 'textfield', '#title' => t('Number of horns?'), '#states' => array( 'visible' => array( ':input[name="pet_type"]' => array('value' => t('Unicorn')), ), ), ); #states Saturday, May 19, 12
  13. Making Complex UX easy ... $form['pet_type'] = array( '#type' =>

    'radios', '#options' => drupal_map_assoc(array(t('Cat'), t('Unicorn'))), '#title' => t('What type of pet do you have?') ); $form['unicorn_horns'] = array( '#type' => 'textfield', '#title' => t('Number of horns?'), '#states' => array( 'visible' => array( ':input[name="pet_type"]' => array('value' => t('Unicorn')), ), ), ); enabled disabled visible invisible checked unchecked expanded collapsed #states Saturday, May 19, 12
  14. Making Complex UX easy ... $form['pet_type'] = array( '#type' =>

    'radios', '#options' => drupal_map_assoc(array(t('Cat'), t('Unicorn'))), '#title' => t('What type of pet do you have?') ); $form['unicorn_horns'] = array( '#type' => 'textfield', '#title' => t('Number of horns?'), '#states' => array( 'visible' => array( ':input[name="pet_type"]' => array('value' => t('Unicorn')), ), ), ); enabled disabled visible invisible checked unchecked value required optional filled empty #states Saturday, May 19, 12
  15. Making Complex UX easy ... $form['choice_wrapper']['choice'] = array( '#prefix' =>

    '<div id="poll-choices">', '#suffix' => '</div>', '#theme' => 'poll_choices', ); $form['choice_wrapper']['poll_more'] = array( '#type' => 'submit', '#value' => t('More choices'), ... '#submit' => array('poll_more_choices_submit'), '#ajax' => array( 'callback' => 'poll_choice_js', 'wrapper' => 'poll-choices', 'effect' => 'fade', ), ); #AJAX Saturday, May 19, 12
  16. REusable form elements ... #managed_file hook_element_info() function file_element_info() { $file_path

    = drupal_get_path('module', 'file'); $types['managed_file'] = array( '#input' => TRUE, '#process' => array('file_managed_file_process'), '#value_callback' => 'file_managed_file_value', '#element_validate' => array('file_managed_file_validate'), '#pre_render' => array('file_managed_file_pre_render'), '#theme' => 'file_managed_file', '#theme_wrappers' => array('form_element'), '#progress_indicator' => 'throbber', '#progress_message' => NULL, '#upload_validators' => array(), '#upload_location' => NULL, '#extended' => FALSE, '#attached' => array( 'css' => array($file_path . '/file.css'), 'js' => array($file_path . '/file.js'), ), ); return $types; } Saturday, May 19, 12
  17. REusable form elements ... #managed_file hook_element_info() function file_element_info() { $file_path

    = drupal_get_path('module', 'file'); $types['managed_file'] = array( '#input' => TRUE, '#process' => array('file_managed_file_process'), '#value_callback' => 'file_managed_file_value', '#element_validate' => array('file_managed_file_validate'), '#pre_render' => array('file_managed_file_pre_render'), '#theme' => 'file_managed_file', '#theme_wrappers' => array('form_element'), '#progress_indicator' => 'throbber', '#progress_message' => NULL, '#upload_validators' => array(), '#upload_location' => NULL, '#extended' => FALSE, '#attached' => array( 'css' => array($file_path . '/file.css'), 'js' => array($file_path . '/file.js'), ), ); return $types; } Saturday, May 19, 12
  18. Bossing other people’s forms around hook_form_alter() function anothermodule_form_alter(&$form, &$form_state, $form_id)

    { if ($form_id == 'mymodule_form') { $form['name']['#required'] = FALSE; $form['submit']['#submit'] = array('anothermodule_form_submit'); } } hook_form_alter() & HOOK_FORM_FORM_ID_ALTER() Saturday, May 19, 12
  19. Making Complex UX easy ... #TREE $form['#tree'] = TRUE; $form['home']

    = array( '#type' => 'fieldset', '#title' => t('Home address'), '#collapsible' => FALSE, ); $form['home']['street'] = array( '#type' => 'textfield', '#title' => t("Street"), ); $form['home']['city'] = array( '#type' => 'textfield', '#title' => t("City"), ); $form['home']['state'] = array( '#type' => 'textfield', '#title' => t("State"), ); Saturday, May 19, 12
  20. function mymodule_form_validate(&$form, &$form_state) { if ($form_state['values']['name'] == 'Joe') { form_set_error('name',

    t('Please choose a better name.')); } } function mymodule_form_submit(&$form, &$form_state) { mymodule_save_name($form_state['values']['name']); $form_state['redirect'] = '<front>'; } rocessing forms ... P Validate incoming data ... Process incoming data ... Saturday, May 19, 12
  21. form_state $ • Available during every stage of form processing.

    (Build, validate, Submit) • COntains the values of the submitted form • in multi-page forms can carry information between steps ($form_state[‘storage’]) • COntrols the workflow Saturday, May 19, 12
  22. reviously ... P • USE drupal_get_form() • Drupal automates the

    workflow • Your module returns a $form array • Your module performs validation • Your module handles processing of submitted data. • You can modify other people’s forms without touching their code. Saturday, May 19, 12