Struts2 <s:doubleselect>级联下拉框 详解析
运行环境:myeclipse8.6+jboss5.1+jvm1.6
先看最后目录结构:
直接上源码:
complexFormTag.jsp:
<%@ page language="java" contentType="text/html; charset=gb2312"pageEncoding="gb2312"%><%@ taglib prefix="s" uri="/struts-tags"%><html><head><title>复杂表单标签使用范例</title><s:head /></head><body><h3 align="left">doubleselect标签使用范例</h3><p><s:form name="doubleselectExample"><s:doubleselect label="材料" headerValue="" headerKey="0"list="itemList" listKey="itemId" listValue="item"doubleName="abc" doubleList="materialMap.get(top.itemId)"doubleListKey="materialId" doubleListValue="material" /></s:form></p></body></html>
解析:
若不使用Struts2,则需要结合JavaScript和HTML标签共同开发完成此功能。
doubleselect标签的功能是提供两个有级联关系的下拉框。用户选中第一个下拉框中的某选项,则第二个下拉框中的选项根据第一个下拉框被选中的某选项内容来决定它自己的下拉框选项内容,产生联动效果。
对于代码"materialMap.get(top.itemId)",其中的top返回的是材料类别map集合的value即材料list集合中的材料类对象实例。
最后面会对top更进一步解释。
注意:<s:doubleselect/>标签必须放在<s:form>中,放在普通<form>中会出错,而且s:form必须指定name属性。
另外,希望页面美观的话,希望s:doubleselect标签和左边的字对齐,则指定s:doubleselect属性theme="simple"
希望两个select排成一行(默认是上下行的),则在<s:form></s:form>间加入css样式:
<style>
.nobr br{display:none}
</style>
然后在用<div class="nobr"></div>把<s:doubleselect .. />包起来就可以了!
下面是doubleselect标签的属性列表:
下面通过一张图形象的表示联动关系:
对应的组件:
最后,两个下拉框要联动起来,靠的是“ItemId”与下面"Integer类型变量"的一一对应关系。
<s:doubleselect ...
list="itemList" listKey="itemId" listValue="item"
doubleList="materialMap.get(top.itemId)"doubleListKey="materialId"doubleListValue="material" />
注意,上面的两相同的itemId,这里应该必须一致。
complexFormTagAction.java:
package action;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import com.opensymphony.xwork2.ActionSupport;import model.*;public class ComplexFormTagAction extends ActionSupport {//级联第一个下拉框数据private List<Item> itemList;//级联第二个下拉框数据private Map<Integer, List<Material>> materialMap;public String execute() throws Exception {itemList = new ArrayList<Item>();//循环新建10个类别for (int j = 0; j < 10; j++) {Item item = new Item();item.setItemId(j + 1);item.setItem("类别" + (j + 1));itemList.add(item);}materialMap = new HashMap<Integer, List<Material>>();//循环新建每个类别中的10个材料for (int j = 0; j < 10; j++) {List<Material> materialList = new ArrayList<Material>();for (int i = 0; i < 10; i++) {Material material = new Material();material.setMaterialId(i);material.setMaterial("类别" + (j + 1)+"-->"+"材料"+(i + 1));materialList.add(material);}materialMap.put((j + 1), materialList);}return SUCCESS;}public Map<Integer, List<Material>> getMaterialMap() {return materialMap;}public void setMaterialMap(Map<Integer, List<Material>> materialMap) {this.materialMap = materialMap;}public List<Item> getItemList() {return itemList;}public void setItemList(List<Item> itemList) {this.itemList = itemList;}}
Material.java:
package model;public class Material implements java.io.Serializable {// Fieldsprivate int materialId;private String material;public Material() {}public int getMaterialId() {return this.materialId;}public void setMaterialId(int materialId) {this.materialId = materialId;}public String getMaterial() {return this.material;}public void setMaterial(String material) {this.material = material;}}
Item.java:
package model;public class Item implements java.io.Serializable {private int itemId;private String item;public Item() {}public int getItemId() {return itemId;}public void setItemId(int itemId) {this.itemId = itemId;}public String getItem() {return this.item;}public void setItem(String item) {this.item = item;}}
struts.xml:
<?xml version="1.0" encoding="gb2312"?><!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"><struts> <constant name="struts.i18n.encoding" value="gb2312"/> <package name="OGNLTAG" extends="struts-default"> <action name="complexFormTag" class="action.ComplexFormTagAction"> <result name="success">/jsp/complexFormTag.jsp</result></action> </package></struts>
运行http://localhost:8080/OGNLTAG/jsp/complexFormTag.action
注:后缀是.action而非.jsp,否则异常:
The requested list key 'itemList' could not be resolved as a collection/array/map/enumeration/iterator type.
因为直接访问jsp页面的话,要先经过struts.xml导航,然后才转到调用Action类处理;这样的话"itemList"就没有完成初始化,故而出现上述异常。若直接“.action”去访问Action类的话,就完成初始化操作了,故而" 'itemList' can be resolved as a collection"。
输出结果:
------------------------------------------
最后通过<s:debug />看一下调试结果中的“值栈”:
Struts ValueStack DebugValue Stack Contents
注意上图中materialMap和itemList这两个Action类中有且仅有的两实例属性。从上面的图片可以理解list="itemList" listKey="itemId" listValue="item"doubleName="abc" doubleList="materialMap.get(top.itemId)"
top.itemId:top代表的就是list即"itemList"当前选中的对象, 所以top.itemId对应的就是当前选中的对象Item的ID, materialMap.get(top.itemId)即根据当前选中的对象Item中的ID来取出第二级下拉框的数据集合。