用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的属性即可。希望参考本文档的读者能有所收获,谢谢。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值