Forms Using Tables

A formatting option often used with forms is an html table.  By creating a table with two columns and multiple rows, you can align data input widgets and the descriptive labels that go along with them.

The discussion below describes a basic html form that is embedded in a table.  It also illustrates the use of multiple submit buttons, each with its own name and value attribute, that can be used to signal different user actions.


Example Table

 

Data Object: Person

PersonID
First Name
Middle Name
Last Name
Address
City
State
Zip Code
Home Phone
Work Phone
Fax
Cell Phone
Email
URL
Date Created
Date Modified
Messages:
 

Notice that the table is "live" in the sense that you can click on a button and see the reflect back the various data included in the table as well as an indication of the intended user action.

HTML code for the Example Table

<form action="http://wwwj.cs.unc.edu:8888/jbs/servlet/jbsGetPostEcho" method="post">
<H3 align="center">Data Object: Person</H3>
<input type="hidden" name="dataObject" value="Person">
<table cellpadding="0" cellspacing="4" width="100%" border="0">
<tr>
<td align="right" width="20%"><b>PersonID</b></td>
<td align="left" width="60%"><input type="text" size="25" name="personID" value=""></td>
</tr>
<tr>
<td align="right" width="20%"><b>First Name</b></td>
<td align="left" width="60%"><input type="text" size="25" name="nameFirst" value=""></td>
</tr>
<tr>
<td align="right" width="20%"><b>Middle Name</b></td>
<td align="left" width="60%"><input type="text" size="25" name="nameMiddle" value=""></td>
</tr>
<tr>
<td align="right" width="20%"><b>Last Name</b></td>
<td align="left" width="60%"><input type="text" size="25" name="nameLast" value=""></td>
</tr>
<tr>
<td align="right" width="20%"><b>Address</b></td>
<td align="left" width="60%"><input type="text" size="25" name="address" value=""></td>
</tr>
<tr>
<td align="right" width="20%"><b>City</b></td>
<td align="left" width="60%"><input type="text" size="25" name="city" value=""></td>
</tr>
<tr>
<td align="right" width="20%"><b>State</b></td>
<td align="left" width="60%"><input type="text" size="25" name="state" value=""></td>
</tr>
<tr>
<td align="right" width="20%"><b>Zip Code</b></td>
<td align="left" width="60%"><input type="text" size="25" name="zip" value=""></td>
</tr>
<tr>
<td align="right" width="20%"><b>Home Phone</b></td>
<td align="left" width="60%"><input type="text" size="25" name="phoneHome" value=""></td>
</tr>
<tr>
<td align="right" width="20%"><b>Work Phone</b></td>
<td align="left" width="60%"><input type="text" size="25" name="phoneWork" value=""></td>
</tr>
<tr>
<td align="right" width="20%"><b>Fax</b></td>
<td align="left" width="60%"><input type="text" size="25" name="phoneFax" value=""></td>
</tr>
<tr>
<td align="right" width="20%"><b>Cell Phone</b></td>
<td align="left" width="60%"><input type="text" size="25" name="phoneCell" value=""></td>
</tr>
<tr>
<td align="right" width="20%"><b>Email</b></td>
<td align="left" width="60%"><input type="text" size="25" name="email" value=""></td>
</tr>
<tr>
<td align="right" width="20%"><b>URL</b></td>
<td align="left" width="60%"><input type="text" size="25" name="url" value=""></td>
</tr>
<tr>
<td align="right" width="20%"><b>Date Created</b></td>
<td align="left" width="60%"><input type="text" size="25" name="dateCreated" value=""></td>
</tr>
<tr>
<td align="right" width="20%"><b>Date Modified</b></td>
<td align="left" width="60%"><input type="text" size="25" name="dateModified" value=""></td>
</tr>
<tr>
<td align="right" width="20%"></td>
<td margin-left="2" align="left" width="60%">
<input type="submit" value="Add" name="userAction" style="background-color: rgb(252, 250, 204)">
<input type="submit" value="Search" name="userAction" style="background-color: rgb(224, 250, 226)">
<input type="submit" value="Update" name="userAction" style="background-color: rgb(252, 250, 204)">
<input type="submit" value="Delete" name="userAction" style="background-color: rgb(254, 219, 219)">
<input type="submit" value="Clear" name="userAction" style="background-color: rgb(224, 250, 226)">
<input type="reset" value="Reset" name="userAction" style="background-color: rgb(224, 250, 226)"></td>
</tr>
<tr>
<td align="right" width="20%"></td>
<td align="left" width="60%"><input type="submit" value=" << " name="userAction" style="background-color: rgb(163, 200, 250)"><input type="submit" value="  <  " name="userAction" style="background-color: rgb(163, 200, 250)"><input type="submit" value="  >  " name="userAction" style="background-color: rgb(163, 200, 250)"><input type="submit" value=" >> " name="userAction" style="background-color: rgb(163, 200, 250)"></td>
</tr>
<tr>
<td align="right" width="20%"><b>Messages:</b></td>
<td align="left" width="60%"><textarea rows="4" cols="25" name="messages"></textarea></td>
</tr>
<tr>
<td align="right" width="20%"></td>
<td align="left" width="60%"><input type="submit" value="Select Table" name="userAction" style="background-color: rgb(224, 250, 226)"></td>
</tr>
<tr>
<td align="right" width="20%"></td>
<td align="left" width="60%"><input type="submit" value="Quit" name="userAction" style="background-color: rgb(252, 250, 204)"></td>
</tr>
</table>
</form>

 Processing Form Data

There are a number of option for processing form data. These include CGI programs, Java Server Pages, ASP pages, and Servlets.  The one that will be considered here is Java Servlets.

Form data is made available to the Servlet through the HttpServletRequest parameter passed to both the doGet and doPost methods.  More specifically, it is available through the getQueryString method of the HttpServletRequest.

The programmer must then parse the query string to "get at" the individual parameters such as, in this case, the user's intended action (i.e., userAction) and the various data fields (e.g., nameLast).  This task is made much easier by the HttpUtils.parseQueryString method that both creates a hashtable of attributes and does a URLDecode on the values.

Once the form parameters are loaded into a hashtable , they can be accessed and processed conveneiently. For architectures that use multiple levels and that use the servlet primarily for control, I recommend creating a DataBean, assigning user parameters to it, and passing it to a layer where processing actually begins.  An example of such a bean is shown below.

Data Bean for User Interface Information

package edu.jbs.ooc.databeans;

import java.util.*;

public class UIBean implements Serializable {

	/********************************
	
	Used to carry user requested action 
	and parameters.
	Data derived from Servlet access of 
	HTTP attributes.
	    	
	********************************/
	
	private java.lang.String userAction;
	private java.lang.String dataObject;
	
	private java.util.Hashtable userParams;
	private java.util.Hashtable sysParams;

public UIBean() {
	
	super();

	userParams = new Hashtable();
	sysParams = new Hashtable();	
}

public void deleteUserParam(String s) {
	userParams.remove ( s );
}

public java.lang.String getDataObject() {
	return dataObject;
}

public Object getSysParam( String s ) {
	return sysParams.get( s );
}

public java.util.Hashtable getSysParams() {
	return sysParams;
}

public java.lang.String getUserAction() {
	return userAction;
}

public java.lang.String getUserParam( String s ) {
	return (String)userParams.get( s );
}

public java.util.Hashtable getUserParams() {
	return userParams;
}

public void setDataObject(java.lang.String newDataObject) {
	dataObject = newDataObject;
}

public void setSysParam(java.lang.String k, java.lang.Object v ) {
	sysParams.put ( k, v );
}

public void setSysParams(java.util.Hashtable newSysParams) {
	sysParams = newSysParams;
}
 
public void setUserAction(java.lang.String newUserAction) {
	userAction = newUserAction;
}

public void setUserParam(java.lang.String k, java.lang.String v ) {
	userParams.put( k, v );
}

public void setUserParams(java.util.Hashtable newUserParams) {
	userParams = newUserParams;
}
}  // end UIBean 

Servlet Control Based on Intended Action

Once the user's form data has been packaged, the servlet can use it to easily determine the intended action (e.g., userAction attribute) and and thereby determine which method to call in the next layer of the architecture.  The code segment shown below illustrates this logic.  As will be obvious, actual processing of the data begins in the ProcessUserAction layer of the system.

	    UIBean uiBean = buildUIBean( req );
	    
	    processUserAction = getProcessUserAction ( uiBean, session );
	    String userAction = uiBean.getUserAction();
	    
	   // CONTROL Segment

	   if ( processUserAction == null ) {
	        xml = processUserAction.nullAction();
	    }
	    else if ( userAction.equalsIgnoreCase("getLogon") )  { 
	        xml = processUserAction.getLogon();
	    }
	    else if ( userAction.equalsIgnoreCase("logon") )  { 
	        xml = processUserAction.verifyLogon( uiBean );
	    }
	    else if ( userAction.equalsIgnoreCase("Add")){
	        xml = processUserAction.add( uiBean );
	    }
	    else if ( userAction.equalsIgnoreCase("Search")){
	        xml = processUserAction.search( uiBean );
	    }
	    else if ( userAction.equalsIgnoreCase("Update")){
	        xml = processUserAction.update( uiBean );
	    }
	    else if ( userAction.equalsIgnoreCase("Delete")){
	        xml = processUserAction.delete( uiBean );
	    }
	    else if ( userAction.equalsIgnoreCase("Clear")){
	        xml = processUserAction.clear( uiBean );
	    }
	    else if ( userAction.equalsIgnoreCase("Quit")){
	        xml = processUserAction.quit( uiBean );
	        closeSession();
	        processUserAction = null;
	    }
	    else {
	        xml = processUserAction.nullAction();
	    }
	            
	    // VIEW Segment

	    XSLTransformer.transform ( xml, XSL_FILE, out );
	    out.close();

Architecture

It may be helpful to view a plausible architecture for a complete system that might use a form such as the one shown above as the primary user interface.