用selectOneMenu標籤開發級聯選擇

用selectOneMenu標籤開發級聯下拉選擇
嶽鄉成

環境:jdk1.6.0、jboss-4.2.3.GA、jboss-seam-2.1.1.GA 、My-SQL-5.0.8

一、標籤說明
1. 概要
級聯下拉選擇是最常用的組件之一,它一般是用Ajax來實現的。利用<h:selectOneMenu>,<s:selectItems>,及<a:support>可以很方便的開發級聯下拉選擇。如下圖所示爲一個用<h:selectOneMenu>做的級聯下拉選擇的示例。

級聯下拉選擇示例
上圖中選擇省份,可以動態的得到該省的市(地區),如果再選擇了市可以動態得到該市的所有縣(區)。
2. 標籤屬性
<h:selectOneMenu>
屬性名稱 描述
id 組件標識符
value 下拉框當前的值
required 是否是必輸項
<s:selectItems>
從一個List、Set、DataModel或者Array中創建一個 List<SelectItem> 。
屬性名稱 描述
id 組件標識符
value 一個EL表達式,指定支持 List<SelectItem> 的數據
var 定義迭代期間保存當前對象的本地變量的名稱
label 渲染 SelectItem 時要使用的標籤。可以參考 var 變量
disabled 如果爲true,SelectItem 將被取消渲染。可以參考 var 變量
noSelectionLabel 指定(可選)標籤放在列表的頂部(如果也指定 required="true",那麼選擇這個值將導致驗證出錯)
hideNoSelectionLabel 如果爲true,選擇一個值時,noSelectionLabel 將被隱藏
<a:support>
Ajax4jsf中的一個標籤,該標籤的功能是對標準的jsf組件添加Ajax功能支持。
屬性名稱 描述
id 組件標識符
event 父組件的JavaScript事件屬性的名稱(onclick、onchange等)
actionlistener 方法綁定,當該組件被Ajax請求激活時,將調用該監聽器方法處理該事件。該方法必須爲public的並且接受一個AjaxEvent參數,返回void

二、示例開發
1. JSF Web頁面
<s:div id="chooseareadiv">
<table class="class_tab1" cellspacing="0" bordercolordark="ffffff" cellpadding="1" bordercolorlight="#C0CFE0" border="1" width="100%">
<tr>
<td width="10%" align="center">
<h:outputLabel id="provincesLabel" value="省份(必須):"></h:outputLabel>
</td>
<td width="15%" align="center">
<h:selectOneMenu id="provincesSel" required="false" value="#{temp.province}">
<s:selectItems noSelectionLabel="-請選擇省份-" value="#{locationUtil.provincesList}" var="item" label="#{item.category_name}" itemValue="#{item.category_id}"/>
<a:support event="onchange" actionListener="#{entProfileHome.changeProvince}" reRender="citySel,districtSel"/>
</h:selectOneMenu>
</td>
<td width="20%" align="center">
<h:outputLabel id="cityLabel" value="市(地區)(必須):"></h:outputLabel>
</td>
<td width="15%" align="center">
<h:selectOneMenu id="citySel" required="false" value="#{temp.city}" >
<s:selectItems noSelectionLabel="-請選擇城市-" value="#{locationUtil.getCities(entProfileHome.temp.province)}" var="item" label="#{item.category_name}" itemValue="#{item.category_id}"/>
<a:support event="onchange" actionListener="#{entProfileHome.changeCity}" reRender="districtSel"/>
</h:selectOneMenu>
</td>
<td width="15%" align="center">
<h:outputLabel id="districtLabel" value="縣(區)(必須):"></h:outputLabel>
</td>
<td width="15%" align="center">
<h:selectOneMenu id="districtSel" required="false" value="#{temp.district}">
<s:selectItems noSelectionLabel="-請選擇區-" value="#{locationUtil.getDistricts(entProfileHome.temp.city)}" var="item" label="#{item.category_name}" itemValue="#{item.category_id}"/>
</h:selectOneMenu>
</td>
<td align="center">
<a:commandButton id="addEhrUserButton" value="新建" action="#{Personalinfometion.createEhrUser(entProfileHome.temp.district)}" οnclick="if(!validationDistrict()) return false;" reRender="addpersonalinfodiv" />
</td>
</tr>
</table>
</s:div>
以上頁面代碼中用到三個類(1)temp類,它是用於獲取省、市、縣下拉列表框的當前選擇的值。(2)locationUtil類,它是用於獲取省、市、縣下拉列表框中所有的內容,及發生了onchange事件後的重新獲得市、縣下拉列表框的內容。(3)entProfileHome類。它負責當一個下拉框內容該變時清理它下一級下拉列表框的內容。
2. Java類, Session Bean及接口
EntProfile類定義如下:
/**
* <p>WeeklyPlanAction</p>
*
* 版權 (c) 2009
*
* <p>CIB</p>
*
* 文件歷史
* 日期 作者 描述
* 2009-06-21 xiangcheng.yue 創建
*
*/

package com.tower.ehr.personalinfo;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;

@Name("temp")
@Scope(ScopeType.SESSION)
public class EntProfile{
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getDistrict() {
return district;
}
public void setDistrict(String district) {
this.district = district;
}
private String province;
private String city;
private String district;

}
entProfileHome類定義如下:
/**
* <p>WeeklyPlanAction</p>
*
* 版權 (c) 2009
*
* <p>CIB</p>
*
* 文件歷史
* 日期 作者 描述
* 2009-06-21 xiangcheng.yue 創建
*
*/
package com.tower.ehr.personalinfo;

import org.jboss.seam.annotations.Begin;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.framework.EntityHome;

@Name("entProfileHome")
public class EntProfileHome extends EntityHome<EntProfile> {


@In(required=false)
@Out(required=false)
private EntProfile temp;

/**
* 省份被選擇修改後的ajax事件動作,清空已關聯的市和縣區數據
*/
public void changeProvince(){
temp.setCity(null);
temp.setDistrict(null);
}
/**
* 市被選擇修改後的ajax事件動作,清空已關聯的縣區數據
*/
public void changeCity(){
temp.setDistrict(null);
}
public void startEdit(){
temp = new EntProfile();
temp.setProvince(getInstance().getProvince());
temp.setCity(getInstance().getCity());
temp.setDistrict(getInstance().getDistrict());

}

public void updateEdit(){
getInstance().setProvince(temp.getProvince());
getInstance().setCity(temp.getCity());
getInstance().setDistrict(temp.getDistrict());

update();
temp = null;
}



@Override
@Begin
public void create() {
super.create();
}

public EntProfile getTemp() {
return temp;
}
public void setTemp(EntProfile temp) {
this.temp = temp;
}
}
Session bean類personalinfo的接口定義如下:
package com.tower.ehr.personalinfo.Impl;

import java.util.List;
import javax.ejb.Local;

import com.tower.ehr.entitybean.Category;

@Local
public interface LocationUtilImpl {
public List<Category> getProvincesList();
public List<Category> getCities(String province);
public List<Category> getDistricts(String city);
public void init();
public void destroy();
}
Session bean類personalinfo定義如下:
/**
* <p>LocationUtil</p>
*
* 版權 (c) 2009
*
* <p>CIB</p>
*
* 文件歷史
* 日期 作者 描述
* 2009-06-01 xiangcheng.yue 創建
*
*/

package com.tower.ehr.personalinfo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.ejb.Remove;
import javax.ejb.Stateful;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Observer;
import org.jboss.seam.annotations.Scope;

import com.tower.ehr.entitybean.Category;
import com.tower.ehr.personalinfo.Impl.LocationUtilImpl;

@Stateful
@Name("locationUtil")
@Scope(ScopeType.SESSION)
/**
* * 創建該類是爲了實現personalinfo中的省市縣的級聯。
*/
public class LocationUtil implements LocationUtilImpl{
/** 省的對象List. */
List<Category> provincesList = new ArrayList<Category>();
/** 由省的名稱及所有該省的市的List組成的Map. */
private Map<String, List<Category>> map_cities = new HashMap<String, List<Category>>();
/** 由市的名稱及所有該市的縣的List組成的Map. */
private Map<String, List<Category>> map_districts = new HashMap<String, List<Category>>();
/** 實例化EntityManager。 */

@PersistenceContext
private EntityManager em;
/**
* 取得所有省份數據
*
* @return
*/
public List<Category> getProvincesList() {
return provincesList;
}

/**
* 根據省取得所有市數據
*
* @param province
* @return
*/
public List<Category> getCities(String province) {
return map_cities.get(province);
}

/**
* 根據市取得所有區縣數據
*
* @param city
* @return
*/
public List<Category> getDistricts(String city) {
return map_districts.get(city);
}

/**
* @since 2009-06-01 在應用啓動時取省市縣的數據。
* @return
* @throws
*/
@Observer("org.jboss.seam.postInitialization")
//@Create
public void init() {
/** 市的對象List. */
List<Category> citiesList = new ArrayList<Category>();

provincesList = getProvinces();


for(int i = 0;i<provincesList.size();i++){
List<Category> cityList = getCitiesByProvincesId(provincesList.get(i).getCategory_id());
if(cityList.size()>0){
map_cities.put(provincesList.get(i).getCategory_id(), cityList);
citiesList.addAll(cityList);
}
}


for(int i = 0;i<citiesList.size();i++){
List<Category> districtsList = getDistrictsByCityId(citiesList.get(i).getCategory_id());
if(districtsList.size()>0){
map_districts.put(citiesList.get(i).getCategory_id(), districtsList);
}
}
}


/**
* @since 2009-06-01
* 得到所有省的list。
* @return List<Category>
* @throws
*/
public List<Category> getProvinces() {
List<Category> results = em.createQuery(
"select td from Category td where td.parent_category_id is null"
).getResultList();
return results;
}
/**
* @since 2009-06-01
* 通過省的Id得到所有市的list。
* @return List<Category>
* @throws
*/
public List<Category> getCitiesByProvincesId(String ProvincesId) {
List<Category> results = em.createQuery(
"select td from Category td where td.parent_category_id = "
+ ProvincesId).getResultList();
return results;
}

/**
* @since 2009-06-01
* 通過市的Id得到所有縣的list。
* @return List<Category>
* @throws
*/

public List<Category> getDistrictsByCityId(String CityId) {
List<Category> results = (List<Category>) em.createQuery(
"select td from Category td where td.parent_category_id = "
+ CityId).getResultList();
return results;
}
/**
* @since 2009-06-01
* 效驗是否選擇了縣的下拉框。
* @return boolean
* @throws
*/
public boolean validationDistrict(){
// if(districtId!=null&&districtId!=""){
// return false;
// }
return true;

}
@Remove
public void destroy() {
}
}

4.小結。
利用<h:selectOneMenu>,<s:selectItems>,及<a:support>標籤製作級聯下拉列表過程非常簡單,只需要掌握<h:selectOneMenu>,<s:selectItems>,<a:support>的幾個屬性及深入理解Map的key-value的屬性即可。希望參考本文檔的讀者能有所收穫,謝謝。
發佈了14 篇原創文章 · 獲贊 0 · 訪問量 1514
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章