16 December 2009
Ajax modal windows, the easy way
Last week I wrote about the awesomeness that is the CTools ajax framework. If you’re anything like me, your mind immediately started racing about all the cool possibilities this opens up. One of those cool possibilities is yet another hidden CTools gem, the modal framework. If you’ve ever used panels, then you’ve seen CTools modals in action. In this post, I’ll show you how to use modals, in the same way that panels does.
First things first…
If you missed my last post, chances are that this one will not make any sense. I highly suggest reading it before continuing with this one.
The code above is about as simple as it gets with modal windows. It simply outputs some text and a title in a modal window. The modal library provides a nice utility function for this, ctools_modal_render(). The function builds the necessary ajax command object and passes it to the browser using ctools_ajax_render().
But now for something not so trivial. Arguably the best use case for modal windows is for displaying forms. This is where the modal library really excels. In this example, we will show the user login form in a modal. Your first impulse might be to just send the output of drupal_get_form() to the modal. While this would display the form in the modal, it would not handle all of the submission and validation properly. Normally Drupal form submissions end in a redirect, which would break our ajax callbacks. Luckily, CTools has an answer for this situation. In the ajax context, we use ctools_modal_form_wrapper() to build the form. The one tricky part here, is that we must evaluate the return value of this function. This function returns an array, that may or may not be populated with ajax commands. If the form submission was not completed for any reason, such as validation errors, then the array will have the commands needed to re-display the form, with errors, in the modal window. If the array is empty, then we can assume that the form was submitted properly. In this case, we add one or more ajax commands to the array to let the user know that the form submitted successfully. In the case of our login form, we do that by redirecting the user to their account page.
One thing I forgot to mention, is that ctools_modal_form_wrapper() expects you to pass in a form_state array. drupal_get_form() allows you to pass in additional arguments after the form id, but the ctools form functions expect all arguments to be passed through the form_state array. In the case of modal forms, the form_state must contain at least an ‘ajax’ and a ‘title’ element.
Hopefully, I’ve explained enough so that you can understand what is going on in the above function.
So here is where I will diverge a little bit. While using the CTools modals, I kept wishing that I could use the jQuery UI Dialog widget as the front-end for my modals. So I took the time to build it. Dialog API aims to be functionally equivalent to the modal library, except that it uses jQuery UI. The ajax commands that it exposes are all nearly identical to their modal equivalents, except that the display command allows you to pass an array of options to the Dialog widget. This allows you to control things like height and width from the ajax callback.
And thanks to the insane work of Rob Loach, Dialog API already has a Drupal 7 port. Very exciting stuff.