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.
The plan
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.
Getting started
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:
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:
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.
The /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-ajax
and 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
URI:
The 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.
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.
The form
Our $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
and $form_state
will be processed by dialog_form_prepare()
.
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 close_link_text
.
Some additional options include: submit_autoclose
, submit_redirect
(should be an absolute URL), and submit_js_callback
, which takes an array with behavior
and 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 devtools/components/dialog/dialong.inc
.
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!