get unstuck, in time

16 February 2009

JSF and default form actions

For a major project I'm working on we're using JavaServer Faces.  It has its attractions but it's missing something of the polish I'd expect (they're feverishly working on getting 2.0 out the door, which aims to provide a lot more functionality, particularly for Ajax processing).
One of the stranger side effects of the processing structure of JSF is that all forms post back to the same page.  This makes sense when you consider that the server must perform validation and handle state transitions, and only then can decide to send a new (next) page as a response to a given action.  However, this means that if your form gets submitted without an action button or link being specifically clicked, you won't go anywhere -- even if, as is often the case, there's only one logical action from a form (such as a login form, where the action is, well, to log in).
There are a number of canned solutions for this including custom tags such as the one provided by j4j, but it turns out it's very easy to roll one's own solution.
All you need to know is the ID of the enclosing form, and you simply duplicate the default action by using a non-renderable button and a hidden input field that references it.  This tricks the JSF mechanism into thinking the button has been clicked.
Here's a simplification of our login form using this approach:
<h:form id="loginForm">
<%-- Invisible button --%>
<h:commandButton id="hiddenSubmit" style="display:none" action="#{loginBean.doLogin}" />
<%-- Hidden input to make JSF think the button was clicked --%>
<input type="hidden" name="loginForm:hiddenSubmit" value="" />

<p>Username: <h:inputText id="email" value="#{}" maxlength="255" /></p>
<p>Password: <h:inputSecret id="password" value="#{loginBean.password}" redisplay="false" maxlength="255" /></p>

<%-- Visible button --%>
<h:commandButton value="Log in" action="#{loginBean.doLogin}" />

Labels: , ,


Post a Comment

<< Home

Copyright (C) 2001-2008