Ext学习笔记09 - ComboBox,Store
ComboBox
ComboBox是指下拉菜单,在API中找到ComboBox对应的xtype是 combo
应用 Window 布局的笔记中的窗体,其中性别 Gender 这一项选项只有两个(male, female),可以使用 ComboBox 控件,为Gender 一项加上 xtype,值为 combo
- {
- fieldLabel:"Gender",
- xtype:"combo"
- },
看,已经是一个下拉框的样子了,但是这时Photo中的图片又显示不出来了,还是那个原因,textfield少了一个,需要调整 索引位置。
ComboBox使用的过程中是很复杂的,就像Dojo中的ComboBox 和 FilteringSelect,在实际应用中的根据不同的需求,应用起来非常灵活。
接下来要为下拉框中赋值,Ext 对于数据存取都封装在了data 中,存储数据分为 GroupingStore,JsonStore 和SimpleStore,在这里使用SimpleStore,它是负责解析数据的数据存储器,通常用来存储数组数据,通过ArrayReader来解析读取数组,看一下ArrayReader在API中的定义
在API提供的示例中给出了ArrayReader存储数组数据的方式,了解了这一点,再来看SimpleStore
SimpleStore中有两个重要的也是最常用的构造参数,Fields 和 Data
- data:用来存放SimpleStore目标数据,以数组形式存在
- fields:field对象定义的数组,也可以是field名字的字符串
SimpleStore中定义的数组都是用ArrayReader来读取的,ArrayReader是封装的一个基础工具类,将读取数组这个常用的操作抽取了出来。
ComboBox中两个常用的构造参数 displayField 和 mode:
displayField:
绑定到当前ComboBox中的基础数据的field名字,未定义的默认值为 mode='text' 或 mode='remote'
mode:
ComboBox 加载数据的方式,默认从远程服务器加载,如果ComboBox加载本地数据,需要设置 mode='local'。
在Gender一项中,只要从本地加载数据就可以了,它的值是确定的,并且不需要修改(如果是需要配置的值或者经常变动的值需要从服务器端加载,但是只有当点击ComboBox向下箭头的时候才会从服务器端发出加载数据请求,这样会产生用户体验的延迟)
来看代码:
- {
- fieldLabel:"Gender",
- xtype:"combo",
- /* 显示 data 的 field 名称 */
- displayField:"gender",
- /* 从本地加载数据 */
- mode:"local",
- readOnly:true,
- store:new Ext.data.SimpleStore({
- /* 定义 dataStore 名称 */
- fields:["gender"],
- /* 定义 data 内容 */
- data:[["Male"],["Female"]]
- })
- },
下拉菜单的效果就出来了:
同样需要设置 readOnly 这个参数,避免用户的误操作。但是这样又出现了一个问题,Ext中的ComboBox提供了一种自动匹配的功能,比如下拉菜单中有一系列数据,我们想找到javaeye这样的选项,当输入字母 j 的时候,下拉列表中会查询出所有以 j 开头的字符串,其他的选项不会显示,也就是说,Gender中只有两项male和female,当选择其中之一之后,另外的选项就不会显示了,而且是readOnly,如果第一次操作用户选错了,希望重选就没有办法操作了,除非刷新页面,这样是不合理的。
这种情况下,有另外一个构造参数可以解决这个问题:
当触发下拉动作被激活时执行这一操作。默认的参数是“query” 即执行查询来匹配用户输入结果,使用参数“all” 会显示所有的结果。需要在ComboBox定义中加上这一句:
- /* 显示所有结果 */
- triggerAction:"all",
这样,当选中一个结果之后,再次点击向下箭头,所有的结果都可以被选择。
照葫芦画瓢,在 Depart 这一项也把 textfield 换成 comboBox
首先Depart这个textfield有点长,我们要把它变的短一些,但是前面在整个 Window 的布局中使用的锚点布局而使 width 这个构造参数失效了,要改变 textfield 的长度还是需要 再使用 锚点 来进行调整
- {
- fieldLabel:"Depart",
- anchor:"46.5%"
- }
宽度调整到46.5%以和上面的文本框对齐
- {
- fieldLabel:"Depart",
- xtype:"combo",
- anchor:"46.5%",
- displayField:"depart",
- mode:"local",
- triggerAction:"all",
- store: new Ext.data.SimpleStore({
- fields:["depart"],
- data:[["Sale"],["Development"],["Management"],["Other"]]
- })
- }
宽度设置成46.5%,以便和上面的对齐,效果
成功!
把 depart 这一项内容加载的事件放到 当窗口show的时候默认显示下拉菜单中的第一个选项:
- showLock:false,
- listeners:{
- "show":function(_window){
- if(!_window["showLock"]){
- _window.findByType("textfield")[4].getEl().dom.src = "http://www.cnblogs.com/../image/default_pic.gif";
- _window["showLock"]=true;
- }
- var _depart = _window.findByType("combo")[1];
- var _store = _depart.store;
- _depart.setValue(_store.getAt(0).get("depart"));
- }
- },
这样,window 调用 show 方法的时候就会默认显示第一个值了。
如果下拉列表里面没有我需要的值怎么办? 对于这样的需求可以在 Depart 后面跟上一个按钮,允许用户添加所需要的Depart的值,然后填充到Depart中。
在一行中左边显示 ComboBox, 右边显示 Button 该怎么办呢?这就需要用到前面说到的列布局,需要小改动一下代码:
- {
- fieldLabel:"Address",
- width:"400"
- },{
- xtype:"panel",
- layout:"column",
- baseCls:"x-plaint",
- items:[{
- columnWidth:.5,
- layout:"form",
- labelWidth:45,
- baseCls:"x-plaint",
- items:[{
- fieldLabel:"Depart",
- xtype:"combo",
- anchor:"100%",
- displayField:"depart",
- mode:"local",
- triggerAction:"all",
- store: new Ext.data.SimpleStore({
- fields:["depart"],
- data:[["Sale"],["Development"],["Management"],["Other"]]
- })
- }]
- },{
- columnWidth:.5,
- layout:"form",
- baseCls:"x-plaint",
- bodyStyle:"padding-left: 10px",
- items:[{
- xtype:"button",
- text:"Add Depart"
- }]
- }]
- }
效果:
这里面用到的布局和显示的一些参数,参考Ext学习笔记07 - Window及Window中的布局 就可以了, 都是一样一样一样地。
这篇有点儿长了,下篇继续吧。
这部分的代码:
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <title>ComboBox in Window</title>
- <link type="text/css" rel="stylesheet" href="http://www.cnblogs.com/../ext/resources/css/ext-all.css">
- <script type="text/javascript" src="http://www.cnblogs.com/../ext/adapter/ext/ext-base.js"></script>
- <script type="text/javascript" src="http://www.cnblogs.com/../ext/ext-all.js"></script>
- <script type="text/javascript" src="http://www.cnblogs.com/../ext/build/locale/ext-lang-zh_CN.js"></script>
- <script type="text/javascript">
- Ext.onReady(function(){
- var _window=new Ext.Window({
- title:"New Person",
- width:500,
- height:320,
- plain:true,
- layout:"form",
- defaultType:"textfield",
- labelWidth:45,
- bodyStyle:"padding-top: 10px; padding-left:10px;",
- defaults:{anchor:"95%"},
- items:[{
- xtype:"panel",
- baseCls:"x-plain",
- layout:"column",
- items:[{
- columnWidth:.5,
- layout:"form",
- defaults:{xtype:"textfield", width:170},
- labelWidth:45,
- baseCls:"x-plain",
- /*bodyStyle:"padding-top: 10px; padding-left:10px;",*/
- items:[
- {fieldLabel:"Name"},
- {
- fieldLabel:"Gender",
- xtype:"combo",
- /* 显示 data 的 field 名称 */
- displayField:"gender",
- /* 从本地加载数据 */
- mode:"local",
- /* 显示所有结果 */
- triggerAction:"all",
- readOnly:true,
- store:new Ext.data.SimpleStore({
- /* 定义 dataStore 名称 */
- fields:["gender"],
- /* 定义 data 内容 */
- data:[["Male"],["Female"]]
- })
- },
- {
- fieldLabel:"Age",
- value:"25",
- readOnly:true
- },
- {
- xtype:"datefield",
- format:"Y-m-d",
- value:"1984-12-03",
- readOnly:true,
- fieldLabel:"Birth",
- listeners:{
- "blur":function(_df){
- var _age = _df.ownerCt.findByType("textfield")[2];
- _age.setValue(new Date().getFullYear() - _df.getValue().getFullYear());
- }
- }
- },
- {fieldLabel:"Phone"},
- {fieldLabel:"Email"}
- ]
- },
- {
- columnWidth:.5,
- layout:"form",
- style:"padding:10px 10px 0 10px",
- labelWidth:45,
- baseCls:"x-plain",
- items:[
- {
- xtype:"textfield",
- inputType:"image",
- width:150,
- height:140,
- fieldLabel:"Photo"
- }
- ]
- }
- ]
- },{
- fieldLabel:"ID",
- width:"400"
- },{
- fieldLabel:"Address",
- width:"400"
- },{
- xtype:"panel",
- layout:"column",
- baseCls:"x-plaint",
- items:[{
- columnWidth:.5,
- layout:"form",
- labelWidth:45,
- baseCls:"x-plaint",
- items:[{
- fieldLabel:"Depart",
- xtype:"combo",
- anchor:"100%",
- displayField:"depart",
- mode:"local",
- triggerAction:"all",
- store: new Ext.data.SimpleStore({
- fields:["depart"],
- data:[["Sale"],["Development"],["Management"],["Other"]]
- })
- }]
- },{
- columnWidth:.5,
- layout:"form",
- baseCls:"x-plaint",
- bodyStyle:"padding-left: 10px",
- items:[{
- xtype:"button",
- text:"Add Depart"
- }]
- }]
- }],
- showLock:false,
- listeners:{
- "show":function(_window){
- if(!_window["showLock"]){
- _window.findByType("textfield")[4].getEl().dom.src = "http://www.cnblogs.com/../image/default_pic.gif";
- _window["showLock"]=true;
- }
- var _depart = _window.findByType("combo")[1];
- var _store = _depart.store;
- _depart.setValue(_store.getAt(0).get("depart"));
- }
- },
- buttons:[
- {
- text:"OK",
- handler:function(){
- alert(this.ownerCt.buttons[1].text);
- }
- },
- {text:"Cancel"}
- ]
- });
- _window.show();
- });
- </script>
- </head>
- <body>
- </body>
- </html>