最近使用ExtJS下拉列表框(ComboBox)希望完成一个动态下拉列表的功能,即列表中的数据都通过异步方式查询数据库而来,同时在用户选择了列表中的某个值后,可以从后台正确的获取用户选择项所对应的值。
这就包含了两个步骤:
1:异步方式查询数据库并渲染到ComboBox(下拉列表)中;
2:后台获取前台用户选择的列表项所对应的值;
先来看看怎样使用异步方式查询数据库并渲染到下拉列表框中去。
首先需要指定一个代理,代理的使用是为了屏蔽具体数据来源的不同,即下拉列表框中的内容既可以来自于local(内存),也可以来自于远程(remote,查询数据库等方式)。一个查询远程数据库的代理写法如下所示:
var proxy = newExt.data.HttpProxy({url:"../AjaxServlet?parameter=identityNoTag"});//指定处理Ajax请求的Servlet和参数
该代理的指定了处理请求的Servlet类为AjaxServlet,并且携带了参数parameter。代理创建完毕后需要指定每条记录的解析方式(不知道准确不准确,我是这么理解的),即创建一个Record,一个Record对应着一条记录:
var identityJSON =Ext.data.Record.create([
{name:"parameterName",type:"string",mapping:"parameterName"},//映射列
{name:"parameterValue",type:"string",mapping:"parameterValue"}//映射列
]);
该Record说明了解析JSON数据的方式,即name为parameterName,类型为字符串类型,而值的名称为parameterValue。接下来将创建一个Reader和store,其中reader负责按照Record所指定的方式读取JSON数据,而store则是用于存储解析后的数据的容器。
var reader=newExt.data.JsonReader({},identityJSON);
var store =newExt.data.Store({
proxy:proxy,
reader:reader
});
接下来的工作就是创建一个下拉列表了:
var identity = newExt.form.ComboBox({
fieldLabel: '目前身份',
name:'identity',//重要属性
hiddenName:'identity',//重要属性,后台获取值时需要
readOnly : true,
allowBlank: false,
store:store,
displayField:'parameterName',//显示给用户的字段
valueField:'parameterValue',//显示给用户的字段对应的值
typeAhead: true,
mode: 'remote',//指定数据来源为远程
triggerAction: 'all',
emptyText:'您的身份...',
selectOnFocus:true,
width:190
});
在来看看后台的查询,查询很简单,你可以使用任何查询方式来查询数据库,并将查询好的数据拼装成为JSON数据即可,其中AjaxServlet代码部分如下所示:
public void doPost(HttpServletRequest request,HttpServletResponse response){
String param = request.getParameter("parameter");
if(param!=null&¶m.equals("identityNoTag")){
logger.info("开始获取身份信息!");
//返回JSON类型的数据固定为text/html,如果返回XML类型的数据此处为text/xml
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");//设置编码方式
String identity = "";//定义身份字段存储查询到的信息--JSON格式
try {
identity = new GetJSONQuery().getIdentityJSONStrNoTag();
PrintWriter out = response.getWriter();
out.println(identity);
out.flush();
out.close();
} catch (IOException e1) {
logger.error("获取输出流失败!"+e1);
} catch (Exception e) {
logger.error("获取身份信息失败!"+e);
}
}
}
其中getIdentityJSONStrNoTag方法如下:
/**
* 查询数据库参数表中的用户身份信息封装成为JSON格式的字符串
* @return
* @throws Exception
*/
public String getIdentityJSONStrNoTag() throws Exception{
HQLDAO dao = DAOUtil.getHQLDAO();
StringBuffer identity = new StringBuffer();
identity.append("[");
List<Parameter> queryResult = dao.queryListByQL("select param from Parameter param where parameterKey='identity'");
for(Parameter parameter:queryResult){
identity.append("{parameterName:'"+parameter.getParameterName()+"',");
identity.append("parameterValue:'"+parameter.getParameterValue()+"'},");
}
identity.deleteCharAt(identity.length()-1);//去掉最后一个逗号
identity.append("]");
logger.info("返回的身份信息如下:"+identity.toString());
return identity.toString();
}
使用的Hibernate查询的数据库(查询数据库就不多介绍了,有需要的可以上网查找相关资料),并封装成为了JSON数据,一个封装好的JSON数据如下所示:
[{parameterName:'皇帝',parameterValue:'sf01'},{parameterName:'后宫佳丽',parameterValue:'sf02'},{parameterName:'王公大臣',parameterValue:'sf03'},{parameterName:'太监宫女',parameterValue:'sf04'},{parameterName:'系统管理员',parameterValue:'sf05'}]
接下来我们需要做的就是在后台去获取用户选择的列表项所对应的值,初学EXTJS时包括我在内的许多人都遇到了这样的一个问题:后台能获取到前台下拉列表项显示的字段,却不能获取到显示的字段所对应的值!
产生这个问题是由于ExtJS中的ComboBox具体实现时是通过n多个<div>标签来实现的,代码如下,而一个表单是需要一个类似<input>标签才能将值提交到后台的,而不是<div>标签,所以这就造成了后台没法获取显示的字段对应的值。这时就需要设置一个hiddenName字段,代码如前所示。这样ExtJS会给ComboBox增加一个<input>标签用于提交选中项的值。而后台为了获取前台提交的值,只需要设置一个变量,变量名为hiddenName所指定的值即可。
一个ComboBox标签解析成为Html后如下代码:
<divid="ext-gen231" class="x-layer x-combo-list "style="position: absolute; z-index: 11000; visibility: visible; left:752px; top: 285px; width: 188px; height: 105px;">
<div id="ext-gen233"class="x-combo-list-inner" style="width: 188px; overflow: auto;height: 105px;">
<div id="ext-gen243"class="x-combo-list-item ">
皇帝
</div>
<div class="x-combo-list-item">
后宫佳丽
</div>
<div id="ext-gen275"class="x-combo-list-item ">
王公大臣
</div>
<div class="x-combo-list-item">
太监宫女
</div>
<div class="x-combo-list-itemx-combo-selected">
系统管理员
</div>
</div>
</div>
综上两个问题都解决啦!一个下拉列表跃然屏幕!