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. FAPI
    THE INCREDIBLE
    Saturday, May 19, 12

    View full-size slide

  2. @eojthebrave • [email protected]
    Consulting • Training • Development
    Saturday, May 19, 12

    View full-size slide

  3. @eojthebrave • [email protected]
    Saturday, May 19, 12

    View full-size slide

  4. What are forms and why are they important?
    Saturday, May 19, 12

    View full-size slide

  5. What are forms and why are they important?
    Saturday, May 19, 12

    View full-size slide


  6. Hero:


    Super-Man
    Hulk
    The Joe!



    Other:



    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

    View full-size slide

  7. 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

    View full-size slide

  8. Saturday, May 19, 12

    View full-size slide

  9. Saturday, May 19, 12

    View full-size slide

  10. FAPI
    THE INCREDIBLE
    FAPI = “Forms API”
    Saturday, May 19, 12

    View full-size slide

  11. http://example.com/contact
    I’m on it! Let me
    find the module
    that will build
    that form for you.
    Saturday, May 19, 12

    View full-size slide

  12. $_POST
    http://example.com/contact
    Saturday, May 19, 12

    View full-size slide

  13. “$_POST” ?
    I guess I
    Better
    validate
    that!
    Saturday, May 19, 12

    View full-size slide

  14. 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

    View full-size slide

  15. “$_POST” ?
    Okay, lets try
    this again.
    Holy smokes.
    It actually
    worked that time.
    Now what?
    Saturday, May 19, 12

    View full-size slide

  16. 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

    View full-size slide

  17. 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

    View full-size slide

  18. $form
    Saturday, May 19, 12

    View full-size slide

  19. drupal_get_form(‘module_form’);
    Saturday, May 19, 12

    View full-size slide

  20. drupal_get_form(‘module_form’);
    mymodule_form($form, &$form_state);
    mymodule_form_validate($form, &$form_state);
    mymodule_form_submit($form, &$form_state);
    Saturday, May 19, 12

    View full-size slide

  21. $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

    View full-size slide

  22. $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

    View full-size slide

  23. $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

    View full-size slide

  24. CLICK!
    Saturday, May 19, 12

    View full-size slide

  25. CLICK!
    Saturday, May 19, 12

    View full-size slide

  26. CLICK!
    Saturday, May 19, 12

    View full-size slide

  27. CLICK!
    Saturday, May 19, 12

    View full-size slide

  28. 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

    View full-size slide

  29. 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

    View full-size slide

  30. 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

    View full-size slide

  31. 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

    View full-size slide

  32. Making Complex UX easy ...
    $form['choice_wrapper']['choice'] = array(
    '#prefix' => '',
    '#suffix' => '',
    '#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

    View full-size slide

  33. 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

    View full-size slide

  34. 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

    View full-size slide

  35. 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

    View full-size slide

  36. drupal_get_form(‘module_form’);
    mymodule_form($form, &$form_state);
    mymodule_form_validate($form, &$form_state);
    mymodule_form_submit($form, &$form_state);
    Saturday, May 19, 12

    View full-size slide

  37. 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

    View full-size slide

  38. 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'] = '';
    }
    rocessing forms ...
    P
    Validate incoming data ...
    Process incoming data ...
    Saturday, May 19, 12

    View full-size slide

  39. 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

    View full-size slide

  40. 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

    View full-size slide

  41. hanks!
    T
    @eojthebrave
    Saturday, May 19, 12

    View full-size slide