jsf+a4j 实现下拉框联动
项目一直用jsf做,最近一个需求要做一个下拉框二级联动,第一个下拉框显示节点名称,第二个下拉框根据节点名称动态显示该节点下的证照类型。一开始没考虑用ajax,就在第一个下拉框中用了ValueChangeListener和onchange="submit();",但当第一个下拉框值变后submit激发了查库的过程,对查询结果进行了一次过滤。但不用onchange="submit();"的话,后台bean中定义的ValueChangeListener事件就没法调用。在尝试了其他方法后,最后打算用一下ajax,而且以前也没用过,趁这个机会学习一下。
??? 从网上搜了一通,有dwr和ajax4jsf等开源框架,由于我们组里有个人非常熟悉dwr,而且dwr也支持jsf,所以先用dwr做了一下。由于这个项目查询用的通用的方法,不能自己写sql,用dwr虽然实现了两个下拉框的联动,但是后台查询不起作用,在考虑了技术和时间代价后,决定尝试一下a4j。
??? 从网上下了a4j的jar包和相关doc,开始了艰难的旅程。其实网上有很多用a4j:support标签实现下拉框联动的例子,但在项目中试了一下都不通,第二个select对应的SelectItems在后台的值已经改变,但页面就是不实时更新。后来单独做个测试页面,能跑通。最后发现两个select是在t:dataTable中,上jboss的网站发现ajax4jsf项目已经被jboss的rich项目合并了,下载rich相关的jar包,jsp页面头部加入:<%@ taglib uri="http://richfaces.org/a4j" prefix="a4j"%>
<%@ taglib uri="http://richfaces.org/rich" prefix="rich"%>,然后用rich相关的form,table,column等标签(比如<a4j:form>,<rich:column>等)就能和a4j做到最好的兼容。但是由于界面显示的要求,我们使用的是<t:dataTable>(<%@ taglib uri="http://myfaces.apache.org/tomahawk" prefix="t"%>),第一个下拉框的reRender=""属性若写成select2,就不能更新,若写成两个select所在的table,即reRender="dtable",就可以了,而且这个table要用<a4j:region>标签包含一下。整个form也是用的<a4j:form>。主要代码如下:
<a4j:region>
.......
? <t:dataTable id="dtable" value='#{validatelogManage.ejbWebProxy.queryList}' var="query" newspaperColumns="2">
.......
???? ?<%/* 下拉框1,激发联动 */%>
???????<rich:column ?rendered="#{query.index == 1}">
????????<h:selectOneMenu?? value="#{query.value}"? style="width:160px">?????
?????????<f:selectItems value="#{query.querymap}" />
?????????<a4j:support event="onchange" action="#{validatelogManage.changeSelectMap}" reRender="dtable"/> ??????? ?????????
????????</h:selectOneMenu>?
???????</rich:column>
???????
???????<%/* 下拉框2,被联动*/%>???????
???????<rich:column? rendered="#{query.index == 2}"? >
????????<h:selectOneMenu?? value="#{query.value}" style="width:160px">
?????????<f:selectItems value="#{query.querymap}"/>
????????</h:selectOneMenu>?
???????</rich:column>
.......
? </t:dataTable>
</a4j:region>?
??? bean中的changeSelectMap方法则根据应用的情况更新第二个下拉框的值即可。第一个下拉框的值绑定到了query.value,所以从value的getValue()方法即可得到第一个下拉框所选的值。