通过指定autocompleter标签的formld属性,可以使两个<s:autocompleter>标签关联起来进行联动。如在某些网站的注册系统中,可以选择注册用户所在的省和所有的市,当用户选择某一个省时,在市列表框中就会列出该省所有的市。这个功能使用autocompleter标签非常容易实现。
实现该功能的基木原理是将显示省的autocompleter标签放在<s:form...>标签中,并使用notifyTopics属性发布一个事件。 然后在显示市的autocompleter标签中使用listenTopics属性监听该事件,并通过formld 属性指定<s:fom.../>标签的id值。一旦显示省的autocompleter标签成功发布事件,显示市的autocompleter标签就会立即监听到该事件,提交表单,以获得该省的所有市,并显示在autocompleter标签中。下面的代码显示了省和市的列表。
<!-- autocompleter_form.jsp -->
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>两个autocompleter标签联动</title>
<s:head theme="ajax" />
<style type="text/css">
input {
width: 200px
}
</style>
</head>
<body>
<s:url id="provinces" action="provinces"/>
<s:form id="form">
<s:autocompleter theme="ajax" autoComplete="true" name="province" href="%{provinces}"
notifyTopics="/provinces" forceValidOption="true" />
</s:form>
<s:url id="cities" action="cities" />
<s:autocompleter theme="ajax" href="%{cities}" autoComplete="true"
formId="form" listenTopics="/provinces" forceValidOption="true" />
</body>
</html>
上面代码中的provinces.action和cities.action实际上对应一个Action类,只是它们对应了不同的逻辑处理方法,这两个Action的配置代码如下:
<package name="chapter15" namespace="/chapter15" extends="json-default">
<action name="provinces" class="chapter15.action.CityAction" method="provinces">
<result>/chapter15/provinces.jsp</result>
</action>
<action name="cities" class="chapter15.action.CityAction" method="cities">
<result>/chapter15/cities.jsp</result>
</action>
</package>
从上面的代码可以看出,provinces.action对应了provinces方法,面cties.ation对应了cties方法。CityAction是 一个Action类,在该类中定义了省和市的列表,并提供了一系列的getter和setter方法获得和设置数据,CityAction 类的实现代码如下:
package chapter15.action;
import com.opensymphony.xwork2.*;
import java.util.*;
public class CityAction extends ActionSupport
{
private String province;
private static Map<String, List<String>> provinces = new HashMap<String, List<String>>();
private int cityCount = 0;
static
{
List<String> cities_ln = new ArrayList<String>();
cities_ln.add("沈阳市");
cities_ln.add("大连市");
cities_ln.add("本溪市");
cities_ln.add("抚顺市");
provinces.put("辽宁", cities_ln);
List<String> cities_gd = new ArrayList<String>();
cities_gd.add("深圳市");
cities_gd.add("珠海市");
cities_gd.add("汕头市");
cities_gd.add("江门市");
provinces.put("广东", cities_gd);
List<String> cities_hxj = new ArrayList<String>();
cities_hxj.add("哈尔滨市");
cities_hxj.add("齐齐哈尔市");
cities_hxj.add("大庆市");
cities_hxj.add("佳木斯市");
provinces.put("黑龙江", cities_hxj);
}
// province属性的getter方法
public String getProvince()
{
return province;
}
// province属性的setter方法
public void setProvince(String province) throws Exception
{
this.province = province;
}
// provinces属性的getter方法
public Set<String> getProvinces()
{
return provinces.keySet();
}
public int getProvinceCount()
{
return getProvinces().size();
}
public List<String> getCities()
{
List<String> cities = provinces.get(province);
cityCount = cities.size();
return cities;
}
public int getCityCount()
{
return cityCount;
}
public String provinces() throws Exception
{
return SUCCESS;
}
public String cities() throws Exception
{
return SUCCESS;
}
}
在返回省列表和市列表的过程中涉及了provinces.jsp和cities.jsp页面,这两个页面的代码如下:
<!-- provinces.jsp -->
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
[
<s:iterator status="status" value="provinces" >
["<s:property/>"]
<s:if test="#status.count < provinceCount">
,
</s:if>
</s:iterator>
]
<!-- cities.jsp -->
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
[
<s:iterator status="status" value="cities" >
["<s:property/>"]
<s:if test="#status.count < cityCount">
,
</s:if>
</s:iterator>
]
最后在浏览器中的测试结果如下:
注:在autocompleter_form.jsp文件中formId会将name=“province”的autocompleter标签中的内容提交给CityAction类中的provinces属性,cities.jsp文件中的value=“cities”的cities是通过Action类中的getCities方法返回的值,#status.count返回当前已经迭代的集合元素个数,test=“#status.count<cityCount"表示当小鱼集合中总的元素个数时,则会继续迭代。