I recently introduced the DevTools module, and today I'm going to show you one of my favourite components, dialog, which builds upon the Dialog module (fear not the 7.x-dev version, it's perfectly stable) and allows you to present single- or multi-state forms in a modal.
First and foremost, a small disclaimer: the dialog component was built for use with custom forms, and may not have expected results with forms from core modules.
In the example module we're about to write, we're going to create a page with a link that will open a custom form in a dialog, proceed through three form states, and upon successful submission of the last state, update the original link with new text.
The first thing we're going to do is download & enable the DevTools and Dialog modules, then (in a custom module) load DevTools, and create a menu callback for the page which will contain a link that'll trigger the modal:'example.pages.inc', 'file path' => drupal_get_path('module', 'example'), ); $items['dialog-example'] = array( 'title' => 'Dialog Example', 'page callback' => 'dialog_example_page', 'access callback' => TRUE, ) + $base; return $items; } ?>
As you can see, we're creating a page at the
/dialog-example URI, specifying the
dialog_example_page() function (in example.pages.inc) as the callback, and granting it unrestricted access.
The page callback will look as follows:array( 'class' => array( 'use-ajax', 'use-dialog', ), 'id' => $trigger_id, ), )); return $output; } ?>
In the callback we're loading the Dialog library, and then creating a unique (per page) ID for the link that'll trigger the modal to open (this is necessary so that we can easily target the link for HTML replacement on final form submission) and to make the form aware of this ID, we pass it as the last part of the URI.
/dialog-example/form URI will be created in our
hook_menu(), and the
start part of the URI specifies the initial form state that should be loaded (more on this later). You could add additional arguments to reference the content you're dealing with, user, or anything else that may be useful to your form. The only remaining tidbits is the assignment of
use-dialog classes on the link, both of which are required.
On to the
hook_menu() for the addition of our new
dialog_example_form_ajax_delivery() function will handle the delivery of the AJAX response, while passing through arguments
2 (form state) and
3 (trigger id) to the form.
'ajax', '#commands' => $commands));
dialog_example_form_ajax_delivery() is defined as follows:
dialog_show_form() is, in simplified terms, a wrapper for Drupal's
drupal_build_form() function, and will pass on all arguments following the form id (in our case,
dialog_example_form) to the form builder.
$form will be structured as three top-level state containers (beginning with the
state_ prefix), and a series of child elements for each state. The
$form_state will be updated to contain various settings, and finally,
$form_state will be processed by
The form declares the three top-level state containers and their children as regular FAPI elements. Each state has a child element that will be used to submit that particular state (for example's sake, the second state uses a checkbox).
Finally, we're going to add validation & submit handlers with
drupal_set_message() statements to see how our form submissions are processing:
The dialog settings configured in
$form_state specify each state, its title and an array of options passed to the actual jQuery Dialog plugin. Furthermore, the
submit key specifies an array of elements which trigger the state's form submission. The
element key should contain a reference to the element within
$form, while the optional
next_state key specifies the next form state to load (this could be used to jump to any state); since this key is optional, a single form can be used for multiple "stand-alone" form states.</code>
By default, a 'Cancel' link is appended to each form state, but this can be disabled with the
close_link key, and its text can be changed by using
Some additional options include:
submit_redirect (should be an absolute URL), and
submit_js_callback, which takes an array with
method keys that specify the JS method to call upon successful form submission. For example, the values
will result in
Drupal.behaviors.example.form_submit_js_callback() being called.
If you're interested in seeing the internal details of how DevTools' Dialog component works, have a look at
This wraps up the process of creating multi-step forms in modals with quite a bit of additional functionality. If you have any questions, hit the comments below!