Dynamic forms in Struts 1

Author: Kasper B. Graversen, 12/12/07
Keywords: Struts, Struts Actions, Struts Forwards
Abstract: Dynamic forms in Struts 1
subscribe to my RSS feed


Bookmark and Share


Dynamic forms in Struts 1

To effectively build a dynamic form, set up an action that is executed befor the form is being displayed. In this action, you can pre-populate information (e.g. restore data retrieved from the DB).
typically you have the actions goToForm, submitForm

struts-config.xml

First we need to define the action for setting up the form, the receiver of the form and the form itself
...
  <form-beans>
  	<form-bean name="formBExample" type="com.yourcompany.struts.ExampleBForm"/>
  </form-beans>
...
  <action-mappings>
  	<action path="/goExampleB"
  		type="com.yourcompany.actions.GoExampleBAction">
  		<forward name="success" path="/exampleB.jsp" />
  	</action>

  	<action path="/submitExampleB"
  		name="formBExample"
  		type="com.yourcompany.actions.SubmitExampleB"
  		input="/exampleB.jsp"
  		validate="true"
  		scope="request">

  		<forward name="success" path="/success.jsp" />
  		<forward name="failure" path="/exampleB.jsp" />
  	</action>
  </action-mappings>
...
</struts-config>

Actions

We then need to create the action that sets up the data needed for the dynamic form, and the action to finally receive the input.
package com.yourcompany.actions;
public class GoExampleBAction extends Action {
	public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest req, HttpServletResponse arg3) throws Exception {
		ExampleBForm f = new ExampleBForm();
		// simulate pre-loading stuff
		f.setBatchName("some name..");
		Line l = new Line(); l.setQuantity(55); f.getBatchLines().add(l);

		req.setAttribute("formBExample", f);
		return mapping.findForward("success");
	}
}
notice how the form is put on the request by the same name as defined in the struts-config.xml!

and the receiver is in our case a simulation that the form is always invalid (to show that in case the form is invalid, that it can display itself with new values rather than resetting to the values setup by the GoExampleBAction
package com.yourcompany.actions;
public class SubmitExampleB extends Action {
	public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest req, HttpServletResponse arg3) throws Exception {
		// validate
		return mapping.findForward("failure"); // simulate failure and let the user continue
	}
}

The form

The form carries a normal textfield, and an array of quantities. Again here are a number of pitfalls!
  • reset() must reset the arraylist.
  • getBatchLine() corresponds to the array list with the "s" omitted and automatically creates missing entries using the while-loop.
  • getBatchLines() corresponds to a normal getter for an array.
package com.yourcompany.struts;
import java.util.Date;
import java.util.ArrayList;
public class ExampleBForm extends ActionForm {
	String batchName;
	ArrayList batchLines = new ArrayList();

	public ExampleBForm() {
		getBatchLine(10);
	}

	public ActionErrors validate(ActionMapping map, HttpServletRequest req) {
		ActionErrors errors = new ActionErrors();
		// errors.add("textfieldErrorPlace", new ActionMessage("error.textfield"));
		return errors;
	}

	public void reset(ActionMapping arg0, HttpServletRequest request) {
		batchLines = new ArrayList();
	}

	public Line getBatchLine(int index) {
		while(index >= batchLines.size())
			batchLines.add(new Line());
		return (Line) batchLines.get(index);
	}

	// -------- generated
	public ArrayList getBatchLines() {
		return batchLines;
	}
	public void setBatchLines(ArrayList batchLines) {
		this.batchLines = batchLines;
	}
	public String getBatchName() {
		return batchName;
	}
	public void setBatchName(String batchName) {
		this.batchName = batchName;
	}
}
and the line entries
package com.yourcompany.struts;
public class Line {
	int quantity;

	public int getQuantity() {
		return quantity;
	}
	public void setQuantity(int quantity) {
		this.quantity = quantity;
	}
}

The view - exampleB.jsp

<%@ page language="java" pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>

<html:html lang="true">
<head><html:base /><title>hello world</title></head>
<body>

<html:form action="/submitExampleB">
batch name: <html:text property="batchName" />
<br>
<table>
<logic:iterate id="batchLine" property="batchLines" name="formBExample" type="com.yourcompany.struts.Line" indexId="row" scope="request">
<tr><td>quantity <html:text name="batchLine" indexed="true" property="quantity" styleId='<%="quantity_" + row%>' /></td></tr>
</logic:iterate>
</table>
<p/>
<html:submit/>
</html:form>
</body>
</html:html>
There are several pitfalls with the above code
  • Sometimes the type and the scope attribute to the logic:iterate tag must be omitted. this depends on the webserver and your version of Struts
  • In order for the array to be re-populated upon a validation failure, the id="batchLine" must match the get method of your form (with is getBatchLine()
  • the attribute styleId serves as the name used by subsequent javascript. It will be translated into an id attribute in the final HTML. Further notice how we assign each cell a unique name by using the row-index. this makes it easy to create javascript that traverses the whole list of cells.



Comments

If you have any comments to this article, please drop me a mail at firstclassthoughts at gmail dot com please indicate if I can't publish whole or parts of your comment on the site.


If you like this site consider subscribing to my RSS feed or how about subscribing by Email.


Help spread the word

Share this post on your favorite social bookmarking sites:
If you enjoyed this article, found it thought provoking, educative or otherwise good, please link to this page from your page or social bookmarking page. If you have any texts you think are worth publishing on First Class Thoughts, don't hesitate to send me a mail! Quality always welcome.


Bookmark and Share


The most recent contributions
28/07/09 Magic in mathematics II Fun with the number cyclic numbers, and specifically with 142857 as it is the smallest of such numbers.
13/07/09 My top 8 time-saving Firefox shortcuts This article presents my favorite top 8 time-saving shortcuts in Firefox 3.0 and Firefox 3.5. Get to know these and you'll be saving a lot of time. They have been ordered by "the element of most surprise"
20/05/09 Board Game Jungle speed / Arriba Review of the cool game "Jungle Speed" aka. "Arriba".
16/05/09 Danish Twin words "Twin words" are words that not only have multiple meanings, they must be composed next to each other in meaningful sentences. This article explores the concept of twin words.
Nothing of interest? Try browsing the entire article archive...