Thoughts on…

Java Middleware & Systems Management

HTML Odyssey – Form Submissions

with one comment

When developing any sufficiently complex web application, there will come a time when you need to support forms that have multiple submit buttons that do different things.  In the case of the RHQ platform, this is unavoidable.  In order to deal with the massive amounts of data RHQ is managing, many of the views are structured as tables where you can select one or many rows and simultaneously perform actions against them.

By default, the first button in the form is the handler for the enter key (as opposed to the act of explicitly clicking on some button to execute a specific action).  While it may seem like we’re picking nits here, having support for resetting what the “default button” is within your form actually goes a long way towards the intuitiveness of your application.  This is evidenced by the fact that JBoss Seam has a standard tag for this:

<s:defaultAction />

Unfortunately, however, this does not work generically across the board.  Since the JSF component developer has quite a bit of freedom in terms of how he/she can write the component implementation, I surmise that JBoss Seam needed to limit its support to a subset of components (perhaps even within a specific version range) to ensure compatibility and proper functioning.  The Seam JSF controls documentation confirms as much…but I’ll discuss more on that later.

I have to admit, I did think of using a javascript-based solution at first, but after giving it some thought I decided it was unnecessarily complicated for the task at hand.  I would have had to capture the enter key event at a global level and click the proper button to simulate a default action, not to mention dealing with potential differences across various browsers RHQ needs to support (for instance, do I add a listener to the window object or to document object?)

I ended up going with a solution that, believe it or not, actually exploits the problem to produce rather serendipitous results.  Since we already know that the first button in the form is the one that will get the enter key event we can – at the top of the form -try to “mimic” the button we want to be the default.

Truth be told, the solution was an adaption of something that Exuro posted on the webdeveloper.com forums.  His solution works at the pure HTML layer by adding:

<input type=”submit” value=”Submit I want to be default” name=”B2″/>

to the top of his form, and then wraps it in some kind of div that is either hidden, or taken out of the page flow and positioned off screen (thus making it effectively hidden).  However, since RHQ is deeply engrossed in JSF-land, the solution needed a slight tweak.  I couldn’t use a simple input control with a name attribute because the existing JSF navigation rules expect an outcome (a String return value), which in this case requires a method binding be present.  Luckily, Exuro’s solution translated nicely up to the JSF layer:

<h:commandButton name=”B2″ value=”#{someBean.someValue}” action=”#{someOtherBean.someAction}” />

As all JSF developers will know this tag eventually renders down into a simple input control whose type attribute is “submit” anyway.  So the rendered solution is nearly identical to the solution on the forum…except that it now properly honors the JSF-specific value and action attributes.

OK, so it may not be as pretty as dropping <s:defaultAction> as a child tag of the button that I want to be the default, but there seem to be no restrictions on this solution.  It works cross-browser and it works for any type of control that eventually renders to a button.

Although the Seam documentation says “Currently you can only nest [the defaultAction tag] inside buttons (e.g. <h:commandButton />, <a:commandButton /> or <tr:commandButton />). ” it seems to be slightly more restrictive than meets the eye.  The RHQ project has one component that extends the standard JSF command button to provide enhanced interaction between a button and the tabular results the button is performing actions against.  I tried the Seam solution against that custom component as follows:

<onc:selectCommandButton name=”B2″ action=”#{someBean.someAction}” value=”I should be the default now”  … >
<s:defaultAction />
</onc:selectCommandButton>

Alas, it did not work.  Granted, I did confirm that the defaultAction tag work for h:commandButton and a:commandButton, but it does not seem to respect extensions for either of those components.  That’s what necessitated me to find an alternate solution. And that’s why the blog entry you just finished reading exists.

Written by josephmarques

January 28, 2009 at 10:39 am

Posted in webdev

Tagged with

One Response

Subscribe to comments with RSS.

  1. No JavaScript required – I like it!

    The only thing I’d add is that a comment in the page source describing the purpose of the hidden input would be prudent. Otherwise, some other developer might come along and delete it, not realizing it actually had a purpose.

    ips

    January 28, 2009 at 2:44 pm


Leave a reply to ips Cancel reply