可输入可联想的下拉列表的实现——Ext ComboBox

 

    网上这样的控件不少,有很多实现方法,其中不少的很巧妙。

    例如:在文本框(HTML INPUT)后,添加一个隐藏层,隐藏层上放一个下拉列表,存储了所有可能的元素,每次文本框触发onpropertychange事件,就是对隐藏层上下拉列表数据的过滤显示。而选择下拉列表,则对文本框进行赋值......然后我们可以通过一些CSS技巧,将它的外观调整成一个可输入可联想下拉列表的模样。

    当然,本文并不打算对上述实现方式进行讨论,而是将EXT中一些实用的控件,“便宜地”添加到我们的项目中来(EXT版本1.1.1)。是的,我强调的是“便宜”!

    EXT上有一种控件ComboBox,就包含了这样的特性,而我们要使用它,标准的做法是:

    1. 首先,你需要将ext-1.1.1(如果你要使用它的样式,那么里面的resource是必须的——样式定义,以及它所依赖的图片都放在里面)添加到项目中来,在需要使用ComboBox的页面添加JS(必须)和CSS引用路径:

< link  rel ="stylesheet"  type ="text/css"  href ="../js/ext-1.1.1/resources/css/ext-all.css"   />

< script  type ="text/javascript"  src ="../js/ext-1.1.1/adapter/ext/ext-base.js" > script >
< script  type ="text/javascript"  src ="../js/ext-1.1.1/ext-all.js" > script >

    注意路径哦!

    2. 你需要一个载体,EXT就是这样,布局需要document.body,Grid需要

,而ComboBox则需要一个

< input  type ="text"  id ="local1" />

    3. 新建一个JS文件,其间包括对存储结构的定义和ComboBox属性的定义:

Ext.onReady( function (){
        Ext.QuickTips.init();
    
        
var  data  =  
        [
                [
' 1 ' , ' Lislie ' , ' D005 ' , ' male ' ],
                [
' 2 ' , ' Merry ' , ' D004 ' , ' female ' ],
                [
' 3 ' , ' Edison ' , ' D003 ' , ' male ' ],
                [
' 4 ' , ' Mark ' , ' D002 ' , ' male ' ],
                [
' 5 ' , ' Leeon ' , ' D001 ' , ' male ' ]
        ];
 
        
//  格式化数据
     var  ds  =   new  Ext.data.Store({
                proxy: 
new  Ext.data.MemoryProxy(data),           //  数据源
        reader:  new  Ext.data.ArrayReader({}, [              //  如何解析
            {name:  ' id ' },
                        {name: 
' name ' },
                        {name: 
' depno ' },
                        {name: 
' sex ' }                               
        ])
        });
        ds.load();  
    
        
var  storeList  =   new  Ext.form.ComboBox({        
                store: ds,
                valueField:
' id ' ,      // option.value
                typeAhead: 
true ,
                displayField: 
' name ' ,      // option.text
                triggerAction: 
' all ' ,
                emptyText:
' Select a store... ' ,
                mode: 
' local ' ,
                selectOnFocus:
true ,
                width:
135
        });
    
        storeList.applyTo(
' local1 ' );
});

    上面的数据来源是一个写死的2维数组。同样的道理,你的数据源可以来自一个链接——请求一个页面,而该页面的Response返回一个符合Json格式的字符串(EXT里面最常用的存储方式是JSON),那么Ext.data.Store的定义就变成了这样:

var  store  =   new  Ext.data.Store({
        proxy:
new  Ext.data.ScriptTagProxy({    url: ' http://localhost:17319/KBS/Grid/EditString.aspx ' }),     //  数据源
        reader:  new  Ext.data.JsonReader({       //  解析格式
            totalProperty :  ' totalCount ' ,                 //  用于分页   
            root :  ' root ' ,
            id : 
' id '
        },
        [
                {name: 
' id ' },
                {name: 
' name ' },
                {name: 
' depno ' },
                {name: 
' sex ' }
        ])
});

    如此,需要请求页面返回的String符合这样的格式,例如:

{
        'totalProperty':100,
        'root':[
                {'id':'a1', 'name':'Lislie', 'depno':'D001', 'sex':'Male'},
                {'id':'a2', 'name':'Merry', 'depno':'D002', 'sex':'Female'},
                {'id':'a3', 'name':'Jone', 'depno':'D003', 'sex':'Female'},
                {'id':'a4', 'name':'Mark', 'depno':'D004', 'sex':'Male'}
        ]
}

    网上有不少将DataTable或Model转JSON的工具类,当然也也可以自己写,反射+字符串的拼接。

    3. 最后,将这个JS引用到页面上。那么一个可输入可联想的控件便出来了。这里有一个小的BUG(暂且用这个词吧),ComboBox终究是放在一个上。

    在前台,你可以通过storeList.getValue()获取当前的选中项的option.value(如果是手动输入的项,而非经过联想选中的项,storeList.getValue()得到的是'',你只能获取到storeList.getRawValue()即的value。需要在点击保存按钮时,在onclick事件中将两者的值设置为一致:“οnclick='javascript:storeList.setValue(storeList.getRawValue);'”)。

    而在后台,你无法像操作(功能更强大,允许你输入不存在的项)。如果你的数据库操作放在后台,那么,你只能操作它的Text了,而所谓的可联想、可输入下拉列表,其实是一个糊弄人的文本框而已。

    ------------------------------------------------------------------------------

    老实说,上面的实现过程还是很麻烦,这里有一个很简单的实现方式——其实EXT研发小组已经替我们完成了这一步,是的,仔细看API,你会发现:

    你可以将一个带数据的,一个