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 {
// Fields
private 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 Debug
Value Stack Contents

注意上圖中materialMap和itemList這兩個Action類中有且僅有的兩實例屬性。從上面的圖片可以理解doubleList="materialMap.get(top.itemId)"中的top,它的意思是:the value at the top of the stack 。
用語句<s:property value="top" />,會輸出:action.ComplexFormTagAction@ 1db6a20
<s:property value="materialMap" />,會輸出:{1=[model.Material@.....],2=[...],...,10=[...] }
(不用"#",也就是直接從“值棧”中取值,此處等效于value="top.materialMap")
<s:property value="itemList" />,會輸出:[model.Item@......,model.Item@...,.......]
測試<s:property value="top.itemId" />輸出為空,是因為itemId這個值是要根據listKey才能確定出來的。
可以上面語句看出:top就是指上面圖片中的“Object列”的對象,它有些“Property”,如 texts、materialMap、actionErrors . . .。
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來取出第二級下拉框的數據集合。
