在程序开发过程中,经常要实现级联的作用,比如:省市区的级联,当下拉列表选择了省之后,在市的下拉的时候就应该是该省下的所有城市,而不是全部饿城市,以此类推在选着市区之后在区域也应该是该市下的市区。
其实这种级联的方式,完全可以用一颗树表示,比如省是根节点,其他的都是其孩子的方式表示,但是这里我只用下拉列表的方式实现,毕竟有得地方用这种方式还是有点优势,而且不是很复杂。
其实现的步骤如下:
首先看看JS部分:
建立省市区的三个下拉列表comboBox
var pcombo = new Ext.form.ComboBox({ fieldLabel : '所在省', anchor: '80%', forceSelection : true, selectOnFocus: true, triggerAction: 'all', mode: 'local', store: pdatastore, allowBlank: true, maxHeight:180, valueField : 'pid', displayField : 'pname', applyTo : 'pcombo' }); var ccombo = new Ext.form.ComboBox({ fieldLabel : '所在市', anchor: '80%', forceSelection : true, selectOnFocus: true, triggerAction: 'all', mode: 'local', store: cdatastore, allowBlank: true, maxHeight:180, valueField : 'cid', displayField : 'cname', applyTo : 'ccombo' }); var acombo = new Ext.form.ComboBox({ fieldLabel : '所在区', anchor: '80%', forceSelection : true, selectOnFocus: true, triggerAction: 'all', mode: 'local', store: adatastore, allowBlank: true, maxHeight:180, valueField : 'aid', displayField : 'aname', applyTo : 'acombo' });
这样就定义号了三个级联的comboBox,我这里要实现的是从数据库中加载数据,所有定义一个加载数据的store,其他实现方式如下:
//------------省开始------------------ var precord=[ {name : 'pid',type : 'string'}, {name : 'pname',type : 'string'} ]; var precordHeads = Ext.data.Record.create(precord); var pdatastore = new Ext.data.Store( { proxy:new Ext.data.HttpProxy(new Ext.data.Connection({timeout:0,url:'./json/cascade_findProvinces.action'})), reader : new Ext.data.JsonReader( { root : 'provinces' //后台返回的list集合 }, precordHeads), remoteSort : false }); //----------市开始-------------------- var crecord=[ {name : 'cid',type : 'string'}, {name : 'cname',type : 'string'}, {name : 'pid',type : 'string'} ]; var crecordHeads = Ext.data.Record.create(crecord); var cdatastore = new Ext.data.Store( { proxy:new Ext.data.HttpProxy(new Ext.data.Connection({timeout:0,url:'./json/cascade_findCityByPid.action'})), reader : new Ext.data.JsonReader( { root : 'cities' //后台返回的list集合 }, crecordHeads), remoteSort : false }); //----------区开始-------------------- var arecord=[ {name : 'aid',type : 'string'}, {name : 'aname',type : 'string'}, {name : 'cid',type : 'string'} ]; var arecordHeads = Ext.data.Record.create(arecord); var adatastore = new Ext.data.Store( { proxy:new Ext.data.HttpProxy(new Ext.data.Connection({timeout:0,url:'./json/cascade_findAreaByCid.action'})), reader : new Ext.data.JsonReader( { root : 'areas' //后台返回的list集合 }, arecordHeads), remoteSort : false });
级联下拉列表需要用到comboBox的一个事件,就是当点击第一个(省)的时候,传一个省的id过去在去加载市的数据,在加载市的数据之前,应该先清掉之前的数据,这样可以重复利用,我这里的具体实现方式如下:
pdatastore.load(); //加载store() pcombo.on('select', function(comboBox){ //alert(comboBox.getValue()); ccombo.clearValue(); //清理掉上一次的数据 cdatastore.load({params:{temppid: comboBox.getValue()}}); }); ccombo.on('select', function(comboBox){ acombo.clearValue(); adatastore.load({params:{tempcid: comboBox.getValue()}}); }); acombo.on('select', function(comboBox){ alert(pcombo.getValue()+'-'+ccombo.getValue()+'-'+acombo.getValue()); //获取数据后的响应操作 //pcombo.clearValue(); //ccombo.clearValue(); //acombo.clearValue(); });
到这里就实现了级联下拉列表的js部分,但是要想在页面上显示,把他嵌入到jsp页面中。
<body> 省:<input id=pcombo type="text" /> 市:<input id=ccombo type="text" /> 区:<input id=acombo type="text" /> <!-- comboBox必须放在input标签里面 --> </body>
到这里页面显示部分就算已经完成了,接下来是后台的实现部分,我这里定义了三个POJO分别是省市区,并且通过ID关联起来,具体代码如下:
public class Province {
private String pid;
private String pname;
//相应的get/set方法
}
public class Province {
private String pid;
private String pname;
//相应的get/set方法
}
public class Area {
private String aid;
private String aname;
private String cid;
//相应的get/set方法
}
读取数据库数据的action部分,我这里使用了原始的JDBC代码去读取数据库,方法比较的笨,每次都要开启JDBC的连接和关闭,没有采用工厂的模式,或者框架去实现,也是方便读取数据,这里只是读取简单的数据库表格数据,我个人认为没有必要用到ssh或者ssi之类的,所以我还是选择用JDBC实现,具体代码如下:
package ext.util.comboBox;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import com.opensymphony.xwork2.ActionSupport;
/**
* 下拉列表级联
* @author lizhenbin
*
*/
public class ComboCascadeAction extends ActionSupport {
private List<Province> provinces;
private List<City> cities;
private List<Area> areas;
private String temppid;
private String tempcid;
private int total;
/**
* 查找所有的省信息
* @return
*/
public String findProvinces() throws Exception {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
List<Province> plist = new ArrayList<Province>();
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:ora10g","weibo","weibo");
stmt = conn.createStatement();
rs = stmt.executeQuery("select * from t_province");
while(rs.next()) {
Province temp = new Province();
temp.setPid(rs.getString("PID"));
temp.setPname(rs.getString("PNAME"));
plist.add(temp);
}
this.setProvinces(plist);
conn.close();
stmt.close();
rs.close();
return "success";
}
/**
* 通过省Id查询城市
* @return
* @throws Exception
*/
public String findCityByPid() throws Exception {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
List<City> clist = new ArrayList<City>();
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:ora10g","weibo","weibo");
stmt = conn.createStatement();
rs = stmt.executeQuery("select * from t_city where pid = "+this.temppid+"");
while(rs.next()) {
City temp = new City();
temp.setCid(rs.getString("CID"));
temp.setCname(rs.getString("CNAME"));
temp.setPid(rs.getString("PID"));
clist.add(temp);
}
this.setCities(clist);
conn.close();
stmt.close();
rs.close();
return "success";
}
/**
* 通过城市Id查询区域
* @return
* @throws Exception
*/
public String findAreaByCid() throws Exception {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
List<Area> alist = new ArrayList<Area>();
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:ora10g","weibo","weibo");
stmt = conn.createStatement();
rs = stmt.executeQuery("select * from t_area where cid = "+this.tempcid+"");
while(rs.next()) {
Area temp = new Area();
temp.setAid(rs.getString("AID"));
temp.setAname(rs.getString("ANAME"));
temp.setCid(rs.getString("CID"));
alist.add(temp);
}
this.setAreas(alist);
conn.close();
stmt.close();
rs.close();
return "success";
}
public static void main(String[] agrs) {
ComboCascadeAction c = new ComboCascadeAction();
try {
c.findProvinces();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public List<Province> getProvinces() {
return provinces;
}
public void setProvinces(List<Province> provinces) {
this.provinces = provinces;
}
public List<City> getCities() {
return cities;
}
public void setCities(List<City> cities) {
this.cities = cities;
}
public List<Area> getAreas() {
return areas;
}
public void setAreas(List<Area> areas) {
this.areas = areas;
}
public String getTemppid() {
return temppid;
}
public void setTemppid(String temppid) {
this.temppid = temppid;
}
public String getTempcid() {
return tempcid;
}
public void setTempcid(String tempcid) {
this.tempcid = tempcid;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
}
最后就是struts.xml的配置了,我读取数据的时候用到的是JsonReader所以返回的数据应该是Json类型,所以我的配置信息如下:
<package name="weibo_json" namespace="/json" extends="json-default"> <!-- comboBox级联 --> <action name="cascade_*" method="{1}" class="ext.util.comboBox.ComboCascadeAction"> <result type="json"></result> </action> </package>
到这里级联下拉列表的后台代码实现部分已经完成,接下来就是在数据库中创建表格,因为主要是演示,所以建立的表格比较的简单:
省表:
-- Create table
create table T_PROVINCE
(
PID VARCHAR2(20) not null,
PNAME VARCHAR2(100)
)
tablespace WEIBO_DATA
pctfree 10
initrans 1
maxtrans 255
storage
(
initial 1M
next 1M
minextents 1
maxextents unlimited
pctincrease 0
);
-- Create/Recreate primary, unique and foreign key constraints
alter table T_PROVINCE
add constraint PK_T_PROVINCE primary key (PID)
using index
tablespace WEIBO_DATA
pctfree 10
initrans 2
maxtrans 255
storage
(
initial 1M
next 1M
minextents 1
maxextents unlimited
pctincrease 0
);
市表:
-- Create table
create table T_CITY
(
CID VARCHAR2(20) not null,
CNAME VARCHAR2(100) not null,
PID VARCHAR2(20)
)
tablespace WEIBO_DATA
pctfree 10
initrans 1
maxtrans 255
storage
(
initial 1M
next 1M
minextents 1
maxextents unlimited
pctincrease 0
);
-- Create/Recreate primary, unique and foreign key constraints
alter table T_CITY
add constraint PK_T_CITY primary key (CID)
using index
tablespace WEIBO_DATA
pctfree 10
initrans 2
maxtrans 255
storage
(
initial 1M
next 1M
minextents 1
maxextents unlimited
pctincrease 0
);
区表:
-- Create table
create table T_AREA
(
AID VARCHAR2(20) not null,
ANAME VARCHAR2(20) not null,
CID VARCHAR2(20)
)
tablespace WEIBO_DATA
pctfree 10
initrans 1
maxtrans 255
storage
(
initial 1M
next 1M
minextents 1
maxextents unlimited
pctincrease 0
);
-- Create/Recreate primary, unique and foreign key constraints
alter table T_AREA
add constraint PK_T_AID primary key (AID)
using index
tablespace WEIBO_DATA
pctfree 10
initrans 2
maxtrans 255
storage
(
initial 1M
next 1M
minextents 1
maxextents unlimited
pctincrease 0
);
到这里全部结束,需要级联的数据,自己在数据库表格中加入即可,我的数据库版本是oracle 10g,你也可以换成其他的比如mysql,换的时候记住要把数据库的连接部分改一下,并且加入相应链接数据库的jar就行,本人能力有限,有什么问题还请多多指教。