2008年01月06日
实现背景:在XX系统的页面中,经常需要在页面中使用下拉框增加用户的操作便捷性,而多个下拉框之间没有现成的组件可以实现分层次查询联动。下面以矿井停产影响为例来说明实现方法:(本开发基于Jdeveloper 10g)
实现具体步骤
1、多级分类层次分析(数据只是举例说明):
第一层次
第二层次
第三层次
事故
人身事故
死亡
 
 
重伤
 
非人身事故
 
故障
机械故障
供电
 
 
供水
 
 
主运输机
 
 
煤机
 
 
皮带
 
机电故障
供电
 
 
供水
 
 
主运输机
 
 
煤机
 
 
皮带
检修
日常检修
 
 
预防性检修
 
外部影响
供排水供暖
 
 
仓满
 
 
其他
 
其他影响
过断层
 
 
搬家倒面
 
 
2、在需要进行联动操作的html页面(editEffect.jsp)中
首先在jsp页面引入这两个JS库文件
<script src="../jscript/tree/xmlextras.js" type="text/javascript"></script>
<script src="../jscript/xloadselect.js" type="text/javascript"></script>
然后针对每一层次创建一个下拉框元素
第一层次:注意select元素的名字等于stage1,第一个层次没有上一级,需要自行填充
<select name="stage1" size="1" onChange="cascadeSelect(‘../prodlog/getCascadeNextLevel.do?
event=getNextLevel&first=’+this.value,document.all.stage2);
document.all.EffClass.value=this.value;">
    <option value="">—空—</option>
    <%
       String[][] col=(String[][])request.getAttribute("data");
       if(col!=null){
         for(int i=0;i<col.length;i++)
         {
    %>
   <option value="<%=col[i][0]%>"><%=col[i][1]%></option>
   <%}}%>
   </select>
   <html:hidden property="EffClass" value="" />//隐藏框用来向数据库提交内容
第二层次:select名字等于stage2
<select name="stage2" size="1"
onChange="cascadeSelect(‘/sdsc/prodlog/getCascadeNextLevel.do?
event=getNextLevel&first=’+document.all.stage1.options[document.all.stage1.selectedIndex].value+’&second=’+this.value, document.all.stage3);document.all.EffSubclass.value=this.value;">
</select>
<html:hidden property="EffSubclass" value="" />
第三层次:select名字等于stage3
<select name="stage3" size="1" onchange="document.all.EffDevice.value=this.value;"></select>
3、后台action和操作
在appModel中定义接口和实现
String[][] retSel();//该方法初始化第一个下拉框的内容
//下面的方法根据传递的参数多少决定需要调用那个具体的级联查询方法
String createXmlForSelect(String firstSel,String secondSel,String thirdSel,String fouthSel);
String firstCascade(String firstSel);//查询第二层次内容
String secondCascade(String firstSel,String secondSel);//查询第三层次内容
在appModel实现中键入如下代码;
//获取第一个下拉框的内容,存放进一个二维数组
 public String[][] retSel()
 {
String QryStr="select code_id,code_desc from T_S_CODE where CODE_ENTCODE=
‘EFFECT’  and CODE_ENTCLASS=’*’ and CODE_CLASS=’EFF_TYPE’
order by code_seq asc";
    ViewObject voMin=ModelUtil.recreateDynamicViewObject(this,QryStr);
    RowSetIterator it=ModelUtil.getIrreleIterator(voMin);
    String[][] selContext=new String[it.getRowCount()][2];
    SdLog.debug("显示记录数"+it.getRowCount());
    int icount=0;
    while(it.hasNext())
    {
       Row row=it.next();
       try
       {
       selContext[icount][0]=ModelUtil.getStrColValue(row,"CODE_ID","");
       selContext[icount][1]=ModelUtil.getStrColValue(row,"CODE_DESC","");
       }
       catch(Exception ex)
       {
         ex.printStackTrace();
       }
       icount++;
    }
    return selContext;
 }
//根据传递参数选择需要调用的具体方法
public String createXmlForSelect(String firstSel,String secondSel,String thirdSel,String fouthSel)
 {
    String ret="";
if (null!=firstSel && null!=secondSel){
       ret=secondCascade(firstSel,secondSel);
    }else if (null!=firstSel){
       ret=firstCascade(firstSel);
    }
    return ret;  
 }
//第二层次内容查询存放到xml中
public String firstCascade(String firstSel)
 {
String QryStr="select code_id,code_desc from T_S_CODE where CODE_ENTCODE=
‘EFFECT’ and CODE_ENTCLASS=’"+firstSel+"’ and CODE_CLASS=’"+firstSel+"’
order by code_seq asc";
    SdLog.debug("查询sql="+QryStr);
    ViewObject voMin=ModelUtil.recreateDynamicViewObject(this,QryStr);
    RowSetIterator it=ModelUtil.getIrreleIterator(voMin);
    StringBuffer sb=new StringBuffer();
    sb.append("<?xml version=\"1.0\" encoding=\"gb2312\"?>\n");
    sb.append("<select>\n");
    sb.append(" <option name=\"—空—\" value=\"\" />\n");
    while (it.hasNext()){
      Row row=it.next();
      String codeID=ModelUtil.getStrColValue(row,"CODE_ID","");
      String codeDesc=ModelUtil.getStrColValue(row,"CODE_DESC","");
      sb.append(" <option name=\"").append(codeDesc)
        .append("\" value=\"").append(codeID)
        .append("\" />").append("\n");
    }
    sb.append("</select>\n");
    SdLog.debug(sb.toString());
   return sb.toString();
 }
//第三层次内容查询存放到xml中
public String secondCascade(String firstSel,String secondSel)
 {
String QryStr="select code_id,code_note from T_S_CODE where CODE_ENTCODE=
‘EFFECT’ and CODE_ENTCLASS=’"+firstSel+"’ and CODE_CLASS=’"+secondSel+"’ order by code_id desc,code_seq asc";
    ViewObject voMin=ModelUtil.recreateDynamicViewObject(this,QryStr);
    RowSetIterator it=ModelUtil.getIrreleIterator(voMin);
    StringBuffer sb=new StringBuffer();
    sb.append("<?xml version=\"1.0\" encoding=\"gb2312\"?>\n");
    sb.append("<select>\n");
    sb.append(" <option name=\"—空—\" value=\"\" />\n");
    while (it.hasNext()){
      Row row=it.next();
      String codeID=ModelUtil.getStrColValue(row,"CODE_ID","");
      String codeDesc=ModelUtil.getStrColValue(row,"CODE_NOTE","");
      sb.append(" <option name=\"").append(codeDesc)
        .append("\" value=\"").append(codeID)
        .append("\" />").append("\n");
    }
    sb.append("</select>\n");
    SdLog.debug(sb.toString());
   return sb.toString();
 }
在editEffect.jsp对应的Action中键入如下代码:
 public void initializeModelForPage(DataActionContext ctx)
{
    HttpServletRequest request = ctx.getHttpServletRequest();
    ProdLogAppModule c=getProdLogService(ctx);
request.setAttribute("data",c.retSel()); 
}
然后再创建一个DataPage,分别创建这个DataPage的Action(ProdloggetCascadeNextLevelAction.java)和JSP页面(getCascadeNextLevel.jsp),向这个JSP页面上从你所使用的DataControl拖一个视图到这个JSP页面,然后删除刚才拖动产生的所有信息,只保留一个空的UIModel文件,在struts-config.xml中删除这个DataPage产生的配置信息中的parameter="/prodlog/ getCascadeNextLevel.jsp"。
在ProdloggetCascadeNextLevelAction.java中创建这样的方法:
方法名字onGetNextLevel 和select框的onChange事件中请求链接中的event=getNextLevel对应,只不过第一个字母必须大写
 public void onGetNextLevel(DataActionContext ctx) {
    HttpServletRequest request = ctx.getHttpServletRequest();
    HttpServletResponse response = ctx.getHttpServletResponse();
    String first=request.getParameter("first");
    String second=request.getParameter("second");
    String third=request.getParameter("third");
    String fouth=request.getParameter("fouth");
    ProdLogAppModule c=getProdLogService(ctx);
    String treeXml=c.createXmlForSelect(first,second,third,fouth);
    try{
      response.setContentType("text/xml;charset=gb2312");
      //下面三句代码是清除xml缓存,及时反映数据库内容改变
      response.setHeader("Pragma","No-cache");
      response.setHeader("Cache-Control","no-cache");
      response.setDateHeader("Expires", 0);      
      response.getWriter().write(treeXml);
    }catch(IOException e){
   
    } }