Pre-populating form elements is a very common and important task in a web application. If pre-population is implemented effectively, then a web application becomes both simpler and more robust.
Forms are used for two kinds of operations: editing the database, and defining search criteria.
When editing the database, there are two use cases for forms :
- the "add" use case, where a new record is added to the datastore - here, input items are initially blank, or have default initial values set in their static HTML
- the "change" use case, where an already existing record is to be edited by the user - here, input items are not initially blank, but are dynamically pre-populated with the current values fetched from the database
In both cases, the user makes entries in the form, and then submits it for processing, using a POST. If an error is detected, then there is a "return to sender" operation, and the HTML form is redisplayed, with all its items dynamically pre-populated, showing their most recently entered values. Appropriate error messages are also displayed.
(For forms used for input of search criteria, the behavior is similar to the "add" use case described above, with the important difference that the form uses GET instead of POST.)
How can this behavior be implemented most effectively?
One method uses a single custom Populate tag, and is guided by the aesthetic ideal that adding pre-population to a form should have an absolutely minimal affect on the markup used in the case of a regular, static HTML form. This seems very effective, since
- web page authors do not need to learn anything new, since forms remain almost exactly as they are in the static case
- it radically minimizes the effort needed to implement pre-population
- it reuses request parameters which are already present and already in the form needed for ultimate display
- it couples HTML forms to the details of a domain object only through a simple naming convention, which maps the names of input controls to the getXXX methods of the domain object
- implementations of domain classes need to handle only the case of valid data, so they become smaller and simpler, a class invariant is easy to define, and they can be immutable objects
- the form needs radical alteration from the style used in a simple, static HTML form
- any prototype written in HTML must be either discarded or altered radically
- the web page author is forced to learn the details of multiple custom tags, which are different for each framework
- if the framework is changed, then another set of custom tags must be learned
- pre-population is more of a programming task than a rendering task, but in this style the page author is mainly responsible for its implementation
Example
The web4j framework implements such a Populate tag. Here, a JSP uses the <w:populate> tag to wrap the controls of a <FORM> tag that may need dynamic population. Note how the <w:populate> tag simply wraps the body of the form, and represents an absolutely minimal change to the style used in a simple, static HTML form.
<w:populate using="itemForEdit">
<form action='MemberAction.do' method="post">
<input name="Id" type="hidden">
<table align="center">
<tr>
<td><label>Name</label> *</td>
<td><input name="Name" type="text"></td>
</tr>
<tr>
<td><label>Is Active?</label></td>
<td><input name="Is Active" type="checkbox" value="true"></td>
</tr>
<tr>
<td><label>Disposition</label></td>
<td>
<select name="Disposition">
<option> </option>
<c:forEach var="item" items="${dispositions}">
<option value="${item.id}">${item}</option>
</c:forEach>
</select>
</td>
</tr>
<tr>
<td align="center" colspan=2>
<input type="submit" value="add.edit.button">
</td>
</tr>
</table>
<tags:hiddenOperationParam/>
</form>
</w:populate>
|
|