可输入可联想的下拉列表的实现——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需要<div>,而ComboBox则需要一个<input type="text">:

<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终究是放在一个<input>上。

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

而在后台,你无法像操作<select>一样,获取它的option.value,而只得到它的text。也只能操作这个Text了。

总结:如果你的数据库操作放在前台,那么你完全可以将ComboBox当成一个<select>(功能更强大,允许你输入不存在的项)。如果你的数据库操作放在后台,那么,你只能操作它的Text了,而所谓的可联想、可输入下拉列表,其实是一个糊弄人的文本框而已。

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

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

你可以将一个带数据的<select>轻松的转化为ComboBox,哪怕它是asp的控件<asp:DropdownList>。而这个转化过程,就是ComboBox的一行属性:

var storeList;

Ext.onReady(function(){
Ext.QuickTips.init();
storeList = new Ext.form.ComboBox({
typeAhead: true,
triggerAction: 'all',
emptyText:'Select a store...',
mode: 'local',
selectOnFocus:true,
transform:'AList', // 将已存在select(通过id)直接转ComboBox
width:135
});
})
缺陷是,手动输入的不存在的项,在后台无法取到。

两种方式区别:由于载体的不同,一个<input>,一个<select>,导致在后台,我们取值方法和取的内容也不同。虽然说,两者在外观和功能上一模一样,但后者才能真正算可输入可联想的下拉列表吧!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值