You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by Ray Clough <ra...@allthisisthat.com> on 2007/05/30 02:54:56 UTC
S2 - Ajax Dynamic Double Select Demo - complete code included
A common problem is having two related select controls on a page. Call them
the 'trigger' and the 'target'. This is an ideal use case for Ajax, because
you don't want to refresh the entire page to re-populate the 'target'
control when the user selects something in the 'trigger'. We have produced
a very nice demo of this using the S2 Ajax tags, and I am enclosing the
Action class and a jsp page which give the example. I hope this is useful
to people. It was a difficult problem to solve, not helped by the very poor
quality of the Ajax documentation on the S2 site (sorry for beefing, but I
spent lots of extra hours because of it). The documentation is incomplete,
disorganized, contradictory, and in many cases just plain wrong.
Anyway, here is the example:
The page calling the demo uses a link to
"/greetings/AjaxDynDoubleSelect_setup.action" Here is the mapping of the
action from struts.xml:
<action name="AjaxDynDoubleSelect_*" method="{1}"
class="greetings.struts2.action.AjaxDDS_DemoAction" >
<result name="success" type="tiles" > /greetings/AjaxDemo.jspx </result>
</action>
This is the Action class:
package greetings.struts2.action;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
/**
* @author Ray Clough, Michael Matz.
* Created: May 29, 2007
* Project: GreetingsEarth_S2_S1_Tiles
* Package: greetings.struts2.action
* File: AjaxDDS_DemoAction.java
* <br/>
* Description:
* <br/>
* This Struts-2 Action class is used to handle the data actions for the
* display and function of the Ajax Dynamic Double Select (DDS)
demonstration.
* The point is to use two 'select' controls, which contain related data.
* The first select control, referred to here as the 'trigger', reacts to
* an 'onchange' event to set the contents of the second select control,
* referred to here as the 'target', to a corresponding list. The update
* of the 'target' is done with Ajax, meaning that the entire page does not
* need to be refreshed. This is a common, but fairly trick operation.
*/
public class AjaxDDS_DemoAction extends ActionSupport {
/** Objects implementing 'Serializable' should define 'serialVersionUID' */
private static final long serialVersionUID = -2394017505624866795L;
private Map<String,List<String>> dataModel;
private String triggerVal = null;
/**
* This constructor initializes the data set which is displayed in
* the two select controls.
*/
public AjaxDDS_DemoAction() {
// create the data model
List<String> grains = new ArrayList<String>();
List<String> fruits = new ArrayList<String>();
List<String> veggies = new ArrayList<String>();
List<String> nuts = new ArrayList<String>();
List<String> other = new ArrayList<String>();
grains.add("Wheat"); //$NON-NLS-1$
grains.add("Barley"); //$NON-NLS-1$
grains.add("Oats"); //$NON-NLS-1$
grains.add("Rye"); //$NON-NLS-1$
grains.add("Corn"); //$NON-NLS-1$
fruits.add("Apples"); //$NON-NLS-1$
fruits.add("Oranges"); //$NON-NLS-1$
fruits.add("Limes"); //$NON-NLS-1$
fruits.add("Kumquats"); //$NON-NLS-1$
fruits.add("Dates"); //$NON-NLS-1$
fruits.add("Persimmons"); //$NON-NLS-1$
veggies.add("Leeks"); //$NON-NLS-1$
veggies.add("Onions"); //$NON-NLS-1$
veggies.add("Beans"); //$NON-NLS-1$
veggies.add("Peas"); //$NON-NLS-1$
veggies.add("Carrots"); //$NON-NLS-1$
nuts.add("Pecans"); //$NON-NLS-1$
nuts.add("Pistachios"); //$NON-NLS-1$
nuts.add("Walnuts"); //$NON-NLS-1$
nuts.add("Filberts"); //$NON-NLS-1$
nuts.add("Pinole"); //$NON-NLS-1$
nuts.add("Cashews"); //$NON-NLS-1$
other.add("Ice Cream"); //$NON-NLS-1$
other.add("Chocolate"); //$NON-NLS-1$
other.add("Fudge"); //$NON-NLS-1$
other.add("Pie"); //$NON-NLS-1$
other.add("Cake"); //$NON-NLS-1$
dataModel = new LinkedHashMap<String,List<String>>();
dataModel.put("Grains", grains); //$NON-NLS-1$
dataModel.put("Fruits", fruits); //$NON-NLS-1$
dataModel.put("Vegetables", veggies); //$NON-NLS-1$
dataModel.put("Nuts", nuts); //$NON-NLS-1$
dataModel.put("Other", other); //$NON-NLS-1$
}
/**
* @return The 'setup()' method sets the initial value for the 'trigger',
* which will result in a compatible 'target' list being displayed
*/
public String setup() {
// initial value for TargetList
this.triggerVal = "Grains"; //$NON-NLS-1$
return SUCCESS;
}
/**
* The 'update()' method is called when the user selects a value from
* the 'trigger' list.
*
* @return The method writes the option elements to the response
* output Writer, and returns 'null'. Returning 'null' tells the
* Struts processor that the processing cycle is complete, and the
* page asynchronously displays the returned values.
*/
@SuppressWarnings("nls")
public String update() {
HttpServletRequest request = ServletActionContext.getRequest();
triggerVal = request.getParameter("triggerValue");
System.out.println("update()");
System.out.println("triggerVal = " + triggerVal);
HttpServletResponse response = ServletActionContext.getResponse();
response.setContentType("text/xml");
response.setHeader("Cache-Control", "no-cache");
Collection<String> targetValues = this.getTargetList(triggerVal);
PrintWriter out = null;
try {
out = response.getWriter();
out.print("<select id='targetSelectionId' >");
for (String targetVal : targetValues) {
out.println("<option>" + targetVal + "</option>");
}
out.print("</select>");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
out.flush();
out.close();
}
}
return null;
}
/**
* This method is called by the 'list' attribute on the trigger
* select control.
* @return Returns the collection used to populate the "trigger'
* select box.
*/
public Collection<String> getTriggerList() {
Collection<String> keys = dataModel.keySet();
return keys;
}
/**
* @return Returns the Collection used to populate the 'target'
* select box, which is a function of the selected value in the
* 'trigger' select box.
*/
private Collection<String> getTargetList(String trigger) {
Collection<String> target = dataModel.get(trigger);
if (target == null) {
return Collections.emptyList();
}
return target;
}
/**
* This method is called by the 'trigger' select box, which has
* the 'name' attribute value of 'triggerValue'
* @param trigVal
*/
public void setTriggerValue(String trigVal) {
System.out.println("setTriggerValue() = " + trigVal); //$NON-NLS-1$
if (trigVal == null || trigVal.length() == 0) return;
this.triggerVal = trigVal;
}
/**
* This is called by the s:url tag for the 'target' s:div tag, which
* uses this value to append the initial target value to the url.
* @return Returns the current 'trigger' value.
*/
public String getTriggerValue() {
System.out.println("getTriggerValue() returns: " //$NON-NLS-1$
+ this.triggerVal);
return this.triggerVal;
}
} // end class 'AjaxDDS_DemoAction'
And here is the jsp page (it is in 'jspx' format):
<?xml version="1.0" encoding="UTF-8"?>
<jsp:root version="2.0"
xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:s="/struts-tags"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:tiles="http://struts.apache.org/tags-tiles" >
<jsp:output omit-xml-declaration="true"
doctype-root-element="html"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" />
<jsp:scriptlet>
String basePath = request.getScheme()
+ "://"
+ request.getServerName()
+ ":"
+ request.getServerPort()
+ request.getContextPath();
pageContext.setAttribute("BasePath",basePath);
</jsp:scriptlet>
<jsp:directive.page contentType="text/html" />
<head>
<title>Dynamic Double Select with Ajax</title>
<s:head theme="ajax" />
<meta name='Author' content='Ray Clough' />
<meta name='keywords' content='Greetings Earth - Struts_2 Demo'/>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="cache-control" content="no-cache" />
</head>
<script type="text/javascript">
// <![CDATA[
var basePath = "${BasePath}";
function updateTarget() {
//alert('function: updateTarget()' );
var triggerId = document.getElementById("triggerId");
var triggerValue = triggerId.value;
var triggerWidget = dojo.widget.byId("targetDivId");
//alert(triggerWidget);
var target = document.getElementById("targetDivId");
var url = target.getAttribute("href");
var newUrl = basePath
+ "/greetings/AjaxDynDoubleSelect_update.action?triggerValue="
+ triggerValue;
triggerWidget.setUrl(newUrl);
/* this publishes the topic, which is registered to the div tag,
causing it to refresh itself. */
dojo.event.topic.publish("updateTargetTopic", "triggerValue:" +
triggerValue);
/* this is an alternative to publish (above) */
//triggerWidget.refresh();
}
// ]]>
</script>
<body>
<form id="ddsFormId" >
<table style="width:100%;">
<tr>
<td style="width:25%; text-align:right;" >Trigger: </td>
<td style="width:*%; text-align:left;" >
<s:select id="triggerId" name="triggerValue"
list="triggerList"
onchange="javascript: updateTarget(); " />
</td>
</tr>
<tr>
<td style="width:25%; text-align:right;" >Target: </td>
<td style="width:*; text-align:left;" >
<s:url id="target_url"
value="${BasePath}/greetings/AjaxDynDoubleSelect_update.action" >
<s:param name="triggerValue" value="%{triggerValue}" />
</s:url>
<s:div id="targetDivId"
theme="ajax" listenTopics="updateTargetTopic"
href="%{target_url}" >
FROGS
</s:div>
</td>
</tr>
</table>
</form>
</body>
</jsp:root>
--
View this message in context: http://www.nabble.com/S2---Ajax-Dynamic-Double-Select-Demo---complete-code-included-tf3837616.html#a10865642
Sent from the Struts - User mailing list archive at Nabble.com.
---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org