5. CONTRIB MODULES
• Webform
• Rules Module does some of this very well - d.o/project/rules
• CTools...thanks @mdorrell
• hook_form_alter(&$form, &$form_state, $form_id)
• Other modules...comments?
6. MAKE A DECISION
WHEN MAKING YOUR OWN FORMS
• planning is your best friend
• if you go with contrib...test - test - test.
• Have a read of the .module file
• can you get away with just hook_form_alter()?
8. MODULE BUILDER ALSO
• pulls the hook definitions directly from api.drupal.org
• for lazy developers - reminds you of the params and whether they are
referenced
• noobs/newbs/neubs
• toggle comments
9. drush mbdl
drush mb fapi_demo nodeapi menu form form_alter
Paste the returned code into the MY_MODULE.module file
fapi_demo.module
pass in params
--build
--write --quiet
--parent
--add
--go
drush en fapi_demo
11. UNDERSTAND THE PAST
The release of Drupal 4.7 introduced the Form API, a framework for building, displaying,
validating, and processing HTML forms. With it, forms are defined as structured arrays, and
those structured arrays contain all the information necessary to properly handle the form
throughout its life cycle. This approach also makes it possible for modules to customize other
forms (adding additional fields to a signup page, for example), and allows designers to
customize the on-screen display of forms using overridable theming functions. It also makes
validating form input, and avoiding form tampering, much easier
12. FAPI 1.0 VS 2.0
• Form API 1.0 handled display and submission with drupal_get_form($form_id, $form)
• single function built to process and build, handling a single $form array
• This works for static forms but makes dynamic forms harder
• Form API 2.0 was introduced with Drupal 5
• drupal_get_form($form_id)
• Dedicated functions for processing and building
• Separates unprocessed user values from the outgoing array of user inputs
13. API.DRUPAL.ORG
• http://api.drupal.org/api/drupal/developer--topics--forms_api_reference.html/6
• API Quickstart Guide: http://drupal.org/node/751826
14. #TREE
• form array is written as a tree structure with nested elements
• $form_state[‘values’] returns a flat array that ignores the defined tree
• unless you set #tree => TRUE
• #parents is like #tree
15. #MARKUP
• an element to wrap elements, insert basic html
• any element without a #type attribute defaults to a
markup element
• #prefix and #suffix may be able to achienve what
you are after
• I use this for a lot of js callbacks on the page to
replace, append, prepend etc...
16. QUICK DETOUR FOR hook_theme()
• register your theme functions as you usually would
• also declare a template key to the function and a tpl.php (or whatever your templating
flavor) can be made which is useful if you are working with developers
• this is also something that I have found increasingly more useful with the rise of AJAX
heavy calls.
• there is also a #theme key for every element type allowing for custom theming
through a function or array of functions you want to pass in.
17. #VALUE
• internal form element that never gets printed onto the page.
• not editable by the user
• Can hold sensitive data that a #hidden form field would be wrong for.
• Will be joined into the form array upon submission and placed into
$form_state[‘values’] for future use.
• form_set_value($form_values[‘key’], $data, $form_state)
18. OTHER KEYS WORTH MENTIONING
• #after_build
• #pre-render - you are responsible for returning altered element array
• #post-render - you are responsible for returning the results return $html
24. INITIALIZING THE FORM
• $_POST and $form_build_id exist?
• setting a token -- drupal_private_key -- http://drupal.org/node/28420
• logged in users only anonymous user forms are not unique and are cached
• prevent injection and xss attacks
25. hook_elements()
• this is called from element_info() - collects information on all element properties and
stores them in cache
• custom form elements, extend existing elements
• fivestar module or wysiwyg/tinymce
26. drupal_get_form($form_id)
• most called/commonly used of the FAPI functions
• it returns the output of the rendered form
return drupal_get_form(‘user_register’);
27. hook_forms($form_id, $args)
• analogous to hook_theme but for forms
• validation and submit callbacks are still mapped to the unique form id
29. drupal_submit_form($form_id)
• this is the final step for the developer, i.e. do something
with all of your new data
• When a form submits to itself, drupal_get_form will return
the form to it’s intial page callback unless 1 of two
conditions exist:
• $form_state[‘redirect’]
• $form_state[‘rebuild’] = TRUE
30. drupal_process_form($form_id, &$form, &$form_state)
• “the heart of the form API” --api.drupal.org
• called by drupal_get_form(), drupal_rebuild_form(), and drupal_execute()
• form is built
• validated
• submitted if passes validation or nothing else get in the way
31. hook_form(&$node, $form_state) vs my_function_form(&$form_state)
• hook_form is also used by modules that invoke node forms
and takes a referenced node object
• changes will be seen on the save/edit paths
• this is used to add your own form elements to node content
• replication of what cck does?
• hook_node_info
32. FORM SCENARIOS
• Long Form
• Multistep
• Wizard/Self Building Form
33. LONG FORM
• this is pretty straight forward and comes straight out of the box
using content types and cck
• build your form in the browser interface
34. MULTISTEP
• save the philosophical debate for the end
• keys to multistep are in the form_state[‘rebuild’] and
form_state[‘storage’] settings.
• Beginning in D6, a form is cached after it is built for the first
time. So setting $form_state[‘rebuild’] => TRUE will create a
fresh form and allow you to change the $form array’s
structure and values.
• Storing the form’s values into $form_state[‘storage’] will
cache them for use on the next page
36. CAVEATS AND GOTCHAS
• menu cache
• $form is an array not an object
• forms are cached
• ‘enctype’ => ‘multipart’
• Drupal.behaviors -to bind functions to page load. Plays nice with other Javascript
objects acting on the DOM
37. OTHER FUNCTIONS AND TOPICS
• good practice to use module key within $form_state, i.e. form_state[‘fapi_demo’][], if
you are going to use it to pass values
• $form['destination'] = array('#type' => 'hidden', '#value' => $_GET['q']);
38. FUTURE
• Advanced AJAX - #ajax - BADCAMP
• http://api.drupal.org/api/drupal/includes--ajax.inc/group/ajax_commands/7
• Ctool by earl miles (@merlinofchaos)
• Open discussion
Welcome\nLet’s wait for everyone to settle\n
\n
\n
\n
\n
I’ve made many a module that only implements hook_form_alter\n
\n
stores the hooks in the default directory default.hooks.inc\n
--add Append hooks to module file. Implies '--write --build=code'. Warning: will not check hooks already exist.\n\ndrush dochooks my_module -- inserts hooks into existing modules\n\nremember to clear out unused BS before you try to run the module...\n\nHigher LEVEL\nTelling module builder about your hooks\nLots of contrib modules provide hooks. You can tell module builder about them, so users can easily generate code for your module's hooks in their own modules.\nTo do this, implement hook_module_builder_info() in a file named YOUR_MODULE.module_builder.inc file in your module folder. See the contents of module_builder.module_builder.inc for a detailed example.\n
so before i delve into the api itself, i thought i’d mention why i wanted to give this presentation.\n-learning curve\n-wished someone had started me here\n-because of the loop that the form api takes us through, we learn a lot about drupal, it’s hooks and, most importantly, it’s caches.\n-does anyone share this feeling?\n
there are a few steps\narrays not objects\n
\n
spend some time here\ncheckbox vs checkboxes\n
\n
\n
outside the scope of this talk\ntpl.php is reminiscent of MVC frameworks\n
\n
pass callback function as well as an array of functions for abstracting common tasks that might repeat themselves in other parts of your module and/or form processing\n\n#pre-render called before drupal_render...receives the #element as the param and must return the altered element\n#post-render 2 params “rendered element and its children”\n\nbe careful of overwriting your existing array...you can do a check to see if the properties you are after are set\n\nrules module hooks into these functions\n
GO TO THE SIMPLE #MARKUP, #VALUE EXAMPLE\n
\n
\n
\n
\n
private key is stored in the variables - best not to touch it\n\nif POST exists then we check the cache to see if there is a copy for the current session\nif YES then retrieve cached form and move on to the check if the form was submitted\nif YES we move to the validate functions\nif PASS validate run submit and process values\nif REDIRECT we are off\nif no REDIRECT then redisplay empty form with a message (hopefully)\nif NO check cace, rebuild, set cache, render form\nif NO cached copy, build form, then move to see form was submitted\nNO Post or form_build_id exists then build\n\npg 222 of Pro Drupal 6\n
then element_info is called\nfivestar is pretty straightforward\ntinymce modifies the default properties of the already existing textarea element - changes the #process => ‘callback function called tinymce_process_textarea’\n
\n
This hook allows modules to build multiple forms from a single form "factory" function but each form will have a different form id for submission, validation, theming or alteration by other modules.\n
these are the default callbacks that Drupal tries to match to your unique form id. You can set the #validate and #submit keys on the form, and form elements to instruct your callback to do something special. Those are also called during the drupal_process_form function\n
these are the default callbacks that Drupal tries to match to your unique form id. You can set the #validate and #submit keys on the form, and form elements to instruct your callback to do something special. Those are also called during the drupal_process_form function\n
show http://api.drupal.org/api/drupal/includes--form.inc/function/drupal_process_form/6\n
I though I’d mention hook_node_info here because it doesn’t really jive elsewhere in the presentation\n name\n module\n description\n help\naccepts array with the usual params:\nhas_title => FALSE\nhas_body\n
\n
show hook_form and the returning of the $form\n
\n
&$form\n
\n
\n
show Form API reference D7\nhttp://api.drupal.org/api/drupal/developer--topics--forms_api_reference.html/7\n \n FAPI integration - allows module developers to create new form components using '#type' => 'multiselect'\n\n