当前位置: 代码迷 >> JavaScript >> ExtJS实现上拉列表级联
  详细解决方案

ExtJS实现上拉列表级联

热度:102   发布时间:2012-09-03 09:48:39.0
ExtJS实现下拉列表级联

????? 在程序开发过程中,经常要实现级联的作用,比如:省市区的级联,当下拉列表选择了省之后,在市的下拉的时候就应该是该省下的所有城市,而不是全部饿城市,以此类推在选着市区之后在区域也应该是该市下的市区。

?????? 其实这种级联的方式,完全可以用一颗树表示,比如省是根节点,其他的都是其孩子的方式表示,但是这里我只用下拉列表的方式实现,毕竟有得地方用这种方式还是有点优势,而且不是很复杂。

其实现的步骤如下:

首先看看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就行,本人能力有限,有什么问题还请多多指教。

  相关解决方案