Version 4.10.0

hirondelle.web4j.ui.tag
Class Populate

Object
  extended by SimpleTagSupport
      extended by hirondelle.web4j.ui.tag.TagHelper
          extended by hirondelle.web4j.ui.tag.Populate
All Implemented Interfaces:
JspTag, SimpleTag

public final class Populate
extends TagHelper

Custom tag which populates form controls in a simple, elegant way.

From the point of view of this tag, there are 3 sources of data for a form control:

For reference, here is the logic that defines which data source is used, and related naming conventions :

if a Model Object of the given name is in any scope {
  override the default HTML for each control
  use the Model Object 
  (match control names to getXXX methods of the Model Object)
}
else if the request is a POST  {
  override the default HTML for each control
  must populate every control using request parameter values
  (match control names to request param names) 
}
else if the request is a GET {
  if control name has a matching req param name {
    override the default HTML for each control
    populate control using request parameter values
    (match control names to request param names) 
  }
  else {
    use the default HTML for that control
  }
}

This tag simply wraps static HTML forms. This is very economical since it does not force the page author to completely replace well-known static HTML with a large set of custom tags.

Example use case

This use case corresponds to either an 'add' or a 'change' of a Model Object. The using attribute signifies that a 'change' case is possible. (This example works with an ActionTemplateListAndEdit action.)
<c:url value="RestoAction.do" var="baseURL"/>
<form action='${baseURL}' method="post" class="user-input"> 
<w:populate using="itemForEdit">  
<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>Location</label></td>
 <td><input name="Location" type="text"></td>
</tr>
<tr>
 <td><label>Price</label></td>
 <td><input name="Price" type="text"></td>
</tr>
<tr>
 <td><label>Comment</label></td>
 <td><input name="Comment" type="text"></td>
</tr>
<tr>
 <td align="center" colspan=2>
  <input type='submit' value="Edit">
 </td>
</tr>
</table>
</w:populate>
 <tags:hiddenOperationParam/>
</form>
Here, the itemForEdit Model Object has the following methods, corresponding to the above populated controls :
  public Id getId() {...}
  public SafeText getName() {...}
  public SafeText getLocation() {...}
  public BigDecimal getPrice() {...}
  public SafeText getComment() {...}

Example without using attribute

No using attribute is specified when :

Here is an example of a form used only for 'add' operations :

<w:populate>
<c:url value="AddMessageAction.do?Operation=Apply" var="baseURL"/> 
<form action='${baseURL}' method=post class="user-input">
<table align="center">
<tr>
 <td>
  <label>Message</label> *
 </td>
</tr>
<tr>
 <td>
  <textarea name="Message Body">
  </textarea>
 </td>
</tr>
<tr>
 <td colspan=2>
  <label>Preview First ?</label> <input type="radio" name="Preview" value="true"> Yes
 </td>
</tr>
<tr>
 <td align="center" colspan=2>
  <input type="submit" value="Add Message"> 
 </td>
</tr>
</table>
</form>
</w:populate>
 

Supported Controls

The following form input items are called supported controls here, and include all items which undergo population by this class :

Population is implemented by editing these supported control attributes :

The body of this tag is HTML, with the following minor restrictions:

HTML often allows alternate ways of expressing the exact same thing. For example, the selected attribute can be expressed as selected='selected', or simply as the single word selected - this tag only accepts the second form, not the first. These sorts of restrictions are a nuisance, and result from the way the framework parses HTML internally. Sometimes you will need to tweak your form hypertext in order to let this tag parse the form correctly. Sorry about that.

Warning: unfortunately, INPUT controls of type color and range can't represent nullable items in a database. This is because the (draft) HTML5 specification doesn't allow such controls to POST non-empty values when forms are submitted. The only workaround for this defect of the specification is to define magic values which map to null. Use such controls with caution.

Prepopulating only portions of a form

There is no requirement that the entire HTML form be wrapped by this tag. If desired, only part of a form may be placed in the body of this tag. This is useful when some form controls take a fixed, static value.

Convention Regarding Control Names

This tag depends on a specfic convention to allow automatic 'binding' between supported controls and corresponding getXXX methods of the Model Object. This convention is explained in RequestParameter.

Deriving values from getXXX() methods of the Model Object

The return value is found. Any primitives are converted into corresponding wrapper objects. The Formats.objectToText(java.lang.Object) method is then used to translate the object into text. If the return value of the getXXX is a Collection, then the above is applied to each element.

Escaping special characters

When this tag assigns a text value to the content of an INPUT or TEXTAREA tag, then the value is always escaped for special characters using EscapeChars.forHTML(String).

GET versus POST

This tag depends on the proper GET/POST behavior of forms : a POST request must only be used when an edit to the database is being attempted. (This is the usual style, and would not be regarded by most as being a restriction.)


Constructor Summary
Populate()
           
 
Method Summary
protected  String getEmittedText(String aOriginalBody)
          Emit the possibly-changed body of this tag, by possibly editing supported form controls contained in the body of this tag.
 void setUsing(String aModelObjectKey)
          Key for the Model Object to be used for form population.
 
Methods inherited from class hirondelle.web4j.ui.tag.TagHelper
checkForContent, crossCheckAttributes, doTag, getPageContext, getPageName, getRequest, getResponse
 
Methods inherited from class SimpleTagSupport
findAncestorWithClass, getJspBody, getJspContext, getParent, setJspBody, setJspContext, setParent
 
Methods inherited from class Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

Populate

public Populate()
Method Detail

setUsing

public void setUsing(String aModelObjectKey)
Key for the Model Object to be used for form population.

This attribute is specified only if the form can be used to edit or change an existing Model Object. If the Model Object is present, then it will be used by this tag to populate supported controls.

This tag searches for the Model Object in the same way as JspContext.findAttribute(String), by searching scopes in a specific order : page scope, request scope, session scope, and finally application scope.

Parameters:
aModelObjectKey - satisfies Util.textHasContent(String).

getEmittedText

protected String getEmittedText(String aOriginalBody)
                         throws JspException
Emit the possibly-changed body of this tag, by possibly editing supported form controls contained in the body of this tag.

Specified by:
getEmittedText in class TagHelper
Parameters:
aOriginalBody - is the evaluated body of this tag. If there is no body, or if the body is present but empty, then it is null.
Returns:
the text to display in the resulting web page.
Throws:
JspException

Version 4.10.0

Copyright Hirondelle Systems. Published October 19, 2013 - User Guide - All Docs.