Now getting back to some real blog content, and to clear out some of the backlog…….
Not too long ago, at work, I ran into the problem of using a url backed by a Spring SimpleFormController inside of a Dojo modal dialog widget. The modal dialog was intended to modifiy the properties of some object on the parent page. The goal was to have the dojo dialog open, populate the dialog with the contents of the url, submit the form and if successful, close the dialog and update the parent; otherwise show the errors.
Our solution was to use Prototype’s Ajax.Updater to populate the div and submit the form.
The first step was to import the two javascript libraries we need to use, the aforementioned dojo and
<script type="text/javascript" src="dojo.js"> </script>
<script type="text/javascript" src="prototype.js"> </script>
After that, we needed to write the script to actually open the dialog, populate it, and submit the results.
<script type="text/javascript"> dojo.require("dojo.widget.Dialog"); var popupDialog; var dialogFormUrl; var parentFormId; dojo.addOnLoad(function() { popupDialog = dojo.widget.byId("dialog_id"); }); function hideDialog() { popupDialog.hide(); } function _showDialog() { popupDialog.show(); } function showDialog(formUrl, outerFormId, modelId) { var params = {}; if(typeof modelId != 'undefined') { params = {id: modelId}; } parentFormId = outerFormId; dialogFormUrl = formUrl; new Ajax.Updater( 'dialogForm', dialogFormUrl, {method: 'get', parameters: $H(params).toQueryString(), asynchronous: true, onSuccess: _showDialog}); } function submit() { /* Submit the parent form to save any state changes */ new Ajax.Updater( 'dialogForm', dialogFormUrl, {method: 'post', parameters: Form.serialize('dialogForm'), onComplete: processResult, asynchronous: true}); } function processResult() { var elems = document.getElementsByClassName("errors"); if(elems.length == 0) { refreshWindow(); } } function refreshWindow() { if(typeof refreshParentPanel != 'undefined') { refreshParentPanel(); } else { $(parentFormId).submit(); } } </script>The method
showDialog()
is the entry point into the widget. It’s function is to initialize some global variables and then call Ajax.Updater
. The parameters for the function are formUrl
(the url for Ajax.Updater to retrieve), outerFormId
(the form id of the parent), and modelId
(the id of the model object we are attempting to modify).
Calling Ajax.Updater
using the ‘get’ method triggers the show initial view path in the spring controller. This is exactly as if the user had navigated to the url manually. However, instead of the contents replacing the contents of the browser window, they are placed into a previously hidden div on the parent page.
Our dialog in this case has two buttons: cancel and save. The cancel button calls the hideDialog
function, which simply re-hids the dialog. The save button presents a few more challenges. Simply sumitting the form will not work, since it will cause the whole page to refresh, and not only the dialog. Therefore, the submit action is wrapped with a call to the Ajax.Updater. ‘post’ is specified here to cause the SimpleFormController to use it’s onSubmit methods.
The one remaining hurdle is that the controller returns the http success status code, regardless of validation errors. Therefore, we must use an additional javascript check. By our convention, all error messages have the element class “errors.” Initially, this was so that we could easily make them all red, but it serves a dual purpose of signaling to our method whether or not the popup needs to be hidden, or if the validation errors need to be displayed.
It took a little work but it should be clear to see how you can adapt almost any existing Spring controller to be used inside a modal dojo dialog.