使用过Ext的人都知道,Ext的Combobox只支持单项选择,而项目中我们经常用到多选下拉框,怎么做呢?
OK,目标达到!细心的朋友会发现,这个多选下拉列表使用的就是GridPanel实现的,而GirdPanel是可以支持分页的,那么我们可不以可以搞分页呢?肯定是可以的,但是经过我试了之后发现,加上分页控件后下拉列表展现变得非常难看,这个问题还是留给朋友们实现吧,呵呵可……
很简单,因为Ext给我们提供了继承机制,这也意味着我们可以通过继承Combobox的方式来重写下拉列表的实现,达到多选的目的!
经过查看Combobox的源码我们发现,Combobox的下拉列表是由DataView类来实现的,那么,我们开始大胆的想:我们直接用一个带CheckBox的GridPanal来代替DataView实现可以吗?
OK,当然可以!我自己研究了一下,写了个代码,基本可以实现下拉框多选了:
- Ext.form.MultiSelect = Ext.extend(Ext.form.ComboBox, {
- // 使用积极的初始化模式
- lazyInit : false,
- headerText : "EMPTY",
- resetText : "EMPTY",
- sureText : "EMPTY",
- textValue : "",
- maxHeight : 310,
- beforeSelect : null,
- /**
- * 初始化下拉列表 原来的下拉列表使用DataView类来实现,现在改为使用GridPanel来实现,这样更方便于多选操作
- */
- initList : function()
- {
- if (!this.list)
- {
- var cls = 'x-combo-list';
- this.list = new Ext.Layer( {
- shadow : this.shadow,
- cls : [ cls, this.listClass ].join(' '),
- constrain : false
- });
- var lw = this.listWidth
- || Math.max(this.wrap.getWidth(), this.minListWidth);
- this.list.setWidth(lw);
- this.assetHeight = 0;
- if (this.title)
- {
- this.header = this.list.createChild( {
- cls : cls + '-hd',
- html : this.title
- });
- this.assetHeight += this.header.getHeight();
- }
- this.innerList = this.list.createChild( {
- cls : cls + '-inner'
- });
- this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
- var sm = new Ext.grid.CheckboxSelectionModel();
- var all = this;
- var ht = this.headerText == "EMPTY" ? "选择项目" : this.headerText;
- var rt = this.resetText == "EMPTY" ? "重置" : this.resetText;
- var st = this.sureText == "EMPTY" ? "确定" : this.sureText;
- this.view = new Ext.grid.GridPanel( {
- store : this.store,
- hideHeaders : true,
- applyTo : this.innerList,
- columns : [ sm, {
- header : ht,
- sortable : false,
- dataIndex : this.displayField
- } ],
- viewConfig : {
- forceFit : true
- },
- autoScroll : true,
- width : this.list.getWidth(),
- sm : sm,
- tbar : new Ext.PagingToolbar({ pageSize: this.pageSize, store:this.store}),
- bbar : [ {
- xtype : "button",
- text : rt,
- handler : function()
- {
- all.onReset();
- }
- }, "-", {
- xtype : "button",
- text : st,
- handler : function()
- {
- all.onSure();
- }
- } ],
- iconCls : 'icon-grid'
- });
- // 设置下拉列表的高度,如果超过了最大高度则使用最大高度
- if (this.view.getSize().height > this.maxHeight)
- {
- this.view.setHeight(this.maxHeight);
- }
- // 如果设置了默认值,则在下拉列表中回显
- if (this.value)
- {
- this.setValue(this.value);
- }
- if (this.pageSize)
- {
- /*
- * var pageBar = new Ext.PagingToolbar({ pageSize: 15, store:
- * this.view.getStore(), displayInfo: true });
- * this.view.add(pageBar); this.view.doLayout();
- */
- }
- if (this.resizable)
- {
- this.resizer = new Ext.Resizable(this.list, {
- pinned : true,
- handles : 'se'
- });
- this.resizer.on('resize', function(r, w, h)
- {
- this.maxHeight = h - this.handleHeight
- - this.list.getFrameWidth('tb') - this.assetHeight;
- this.listWidth = w;
- this.innerList.setWidth(w - this.list.getFrameWidth('lr'));
- this.restrictHeight();
- }, this);
- this[this.pageSize ? 'footer' : 'innerList'].setStyle(
- 'margin-bottom', this.handleHeight + 'px');
- }
- }
- },
- /**
- * 确定选择事件
- */
- onSure : function()
- {
- var selecteds = this.view.getSelectionModel().getSelections();
- var value = [];
- var all = this;
- var tv = [];
- Ext.each(selecteds, function(rc)
- {
- value.push(rc.data[all.valueField]);
- tv.push(rc.data[all.displayField]);
- });
- this.textValue = tv.join();
- var valueStr = value.join();
- beforeSelect = this.beforeSelect;
- if(typeof beforeSelect == 'function')
- {
- if(!beforeSelect(valueStr))
- {
- this.collapse();
- return;
- }
- }
- this.setValue(valueStr);
- this.value = value.join();
- this.collapse();
- },
- getTextValue : function(){
- return this.textValue;
- },
- /**
- * 重置事件
- */
- onReset : function()
- {
- this.view.getSelectionModel().clearSelections();
- },
- /**
- * 给ComboBox设置值
- * 设置完全局的值后,再在下拉列表中回显这些值
- */
- setValue : function(v)
- {
- var text = v;
- var ta = [];
- // 根据值查找出名称,并组装显示
- if (this.valueField && v && ("" + v).length > 0)
- {
- var sv = ("" + v).split(",");
- for ( var i = 0; i < sv.length; i++)
- {
- var r = this.findRecord(this.valueField, sv[i]);
- if (r)
- {
- ta.push(r.data[this.displayField]);
- }
- else if (this.valueNotFoundText !== undefined)
- {
- ta.push(this.valueNotFoundText);
- }
- }
- text = ta.join();
- }
- this.lastSelectionText = ta.join();
- if (this.hiddenField)
- {
- this.hiddenField.value = v;
- }
- this.textValue = text;
- Ext.form.ComboBox.superclass.setValue.call(this, text);
- this.value = v;
- // 在下拉列表中回显设置的值
- if (this.view && v && ("" + v).length > 0)
- {
- var sv = ("" + v).split(",");
- var mv = this.view;
- var sr = [];
- var all = this;
- this.store.each(function(item)
- {
- for ( var i = 0; i < sv.length; i++)
- {
- if (sv[i] == item.data[all.valueField])
- {
- sr.push(item);
- break;
- }
- }
- });
- this.view.getSelectionModel().selectRecords(sr);
- }
- },
- /**
- * 触发下拉列表展现 这里不使用ComboBox的查询功能,直接展现
- */
- onTriggerClick : function()
- {
- if (this.disabled)
- {
- return;
- }
- if (this.isExpanded())
- {
- this.collapse();
- }
- else
- {
- this.onFocus( {});
- this.expand();
- this.el.focus();
- }
- }
- });
- <html>
- <head>
- <script type="text/javascript" src="./ext-2.0.2/adapter/ext/ext-base.js"></script>
- <script type="text/javascript" src="./ext-2.0.2/ext-all.js"></script>
- <script type="text/javascript" src="./MultiCombo.js"></script>
- <link rel="stylesheet" type="text/css"
- href="./ext-2.0.2/resources/css/ext-all.css" />
- </head>
- <body>
- <button onclick="showMenu(this)" id="heare">显示值</button>
- <div id="local-states"></div>
- </body>
- <script>
- var store = new Ext.data.SimpleStore({
- fields : ['id', 'text'],
- data : [['1', '一月'], ['2', '三月'], ['3', '二月'], ['4', '四月'],
- ['5', '五月'], ['6', '六月'], ['7', '七月'], ['8', '八月'],['9', '九月'], ['10', '十月'], ['11', '十一月'], ['12', '十二月'],['13', '十三月'], ['14', '十四月'], ['15', '十五月']]
- });
- var combo = new Ext.form.MultiSelect({
- id : 'myCombo',
- name : 'name',
- hiddenName : 'id',
- store : store,
- emptyText : '请选择...',
- mode : 'local',
- value : '5,6,7',
- triggerAction : 'all',
- valueField : 'id',
- displayField : 'text',
- editable : false,
- pageSize : 5,
- beforeSelect : function(selectValues){
- if(selectValues == '5')
- {
- return true;
- }
- else{
- Ext.Msg.alert("alert", "Can not!");
- return false;
- }
- },
- blankText : '请选择...'
- });
- combo.render("local-states");
- function showMenu(){
- alert(combo.getValue());
- }
- </script>
- </html>
OK,目标达到!细心的朋友会发现,这个多选下拉列表使用的就是GridPanel实现的,而GirdPanel是可以支持分页的,那么我们可不以可以搞分页呢?肯定是可以的,但是经过我试了之后发现,加上分页控件后下拉列表展现变得非常难看,这个问题还是留给朋友们实现吧,呵呵可……
由于注册未满一周,不能上传效果图,大家还是拷贝源码下去自己运行吧……