extjs combobox 下拉列表菜单学习

extjs combobox 下拉列表菜单学习

⭐️来自很多年前的extjs笔记,只是一个归档,不做更新!⭐️

常用配置项

  • emptyText: “–请选择–” //没有值时的水印文字。
  • editable : false, //是否可编辑,默认可编辑,所以加上

常用监听事件

afterrender 组件渲染之后触发的事件

listeners : {
	'afterrender': function(){
		Ext.Ajax.request({
				method:'post',
				url:'/JF/PolicyConfig_SqlInjectRule/getCurrentObject',
				success:function(response){
					var res = Ext.decode(response.responseText);
					//console.log(res.now_object);
					Ext.getCmp('databaseObject').setValue(res.now_object);
				}
			});
		
	},
	'change':function( combobox, newValue, oldValue){

combobox 下拉列表菜单学习

下拉列表设置默认值 使用setValue方法,注意传的参数 valueField的值,不是displayField要展现的值,即可展现你的选择

Ext.getCmp('databaseObject').setValue(res.now_object);

设置默认store中的第一行

获取当前下拉菜单的选择值,该组件有直接方法 getValue()

 var currentRuleSet = Ext.getCmp('ruleSet').getValue();

combobox怎么缩小fieldLabel跟下拉框之间的距离

设置labelWidth:80 宽度和表签字的宽度一样,就没有了间距; 宽度越大,间距越明显。
4. 下拉框宽度如何设置?
注意 这里的width是指整个下拉框组件的宽度包含你设置的label宽度,因此你要的下拉那个框的宽度就是
width-labelWidth的宽度

{
	xtype:'combobox',
	name:'enable',
	id:'enable',
	fieldLabel: '是否启用',
	labelWidth:60,
	width: 130,

	store:Ext.create('Ext.data.Store', {
	fields: ['value', 'enable' ],
	data : [
			{"value":"2", "enable":"全部"},
			{"value":"1", "enable":"启用"},
			{"value":"0", "enable":"关闭"}
		]
	}),
	value:'2',
	queryMode: 'local',
	displayField: 'enable',
	valueField: 'value'
},

自定义下拉菜单,然后可以添加一些自己的配置项,在初始化组件时进行一些处理 如这里的 requireable: false, 在配置项在extjs中没有,是自己定义的

在配置该自定义的配置项后,label分割器加*并且布恩那个为空。	
Ext.define('Kitchensink.form.JautoComboBox', {
	extend: 'Ext.form.field.ComboBox',
	alias: 'widget.JautoComboBox',
	editable:false,
	requireable: false,		
	initComponent: function()
	{
		if(this.requireable)
		{
			this.labelSeparator = ':
*
'
; this.allowBlank = false; } this.callParent(); } //multiSelect: true,//支持多选 });

下拉菜单需要一个 全部,初始设置value,但是store从服务器端ajax请求后返回内容没有 全部,选择后就再看不到 全部选项?如何解决

思路1:还是想办法 服务器端返回的内容 加上 全部选项
思路2:前端处理

下拉菜单下方添加一个永久选项,让可以选择触发一个事件,从而弹出表单窗口让新建一个xx

思路:监听前端store的load事件,然后掉store的add方法; add方法刚好,加到下拉列表的最后一项
`
//测试成功,在下拉菜单组件中,添加listeners配置项,监听render方法然后获取该组件的store(getStore),绑定store的load事件方法,在load方法中使用store的add方法

  listeners : {
  	'render':function(combo){
  		//store的load事件setValue第一行
  		combo.getStore().on("load",function(s,r,o){
  			console.log(r[0]);
  			if(typeof r[0] != 'undefined'){
  				combo.setValue(r[0].get('id'));

  			}else{
  				combo.setValue('该对象暂无规则,请新建');							
  			}
  			s.add({id: '0',name: '--新建规则--'});
  		});
  	},


		'change':function( combobox, newValue, oldValue){
			//alert(newValue);
			if(newValue == 0){
				//触发自定义事件
				this.fireEvent('addRuleSet',newValue);
			}else{
	
				var store = Ext.ComponentQuery.query('sqlinjectrulelist')[0].getStore();
				var rurl = '/JF/PolicyConfig_SqlInjectRule/getList?ruleset_id='+newValue;
				store.proxy.url=rurl;
				store.type= 'ajax';
				store.reload();
			}
			
		}
	}

监听下拉框选择事件如上实例,可以监听 change事件
如果newValue是我们想要的值,然后调用fireEvent 触发一个自定义事件
在MVC开发模式下,在control中处理这个事件,如下,在control中下的如下,这里要注意

init: function(){
       console.log('Initialized Users! This happens before ' +
                   'the Application launch() function is called');
	var me = this;
	this.control({
//注意点:view中自定义的别名  组件类型[组件中定义name] //试过直接写sqlinjectrulelist不行,要具体到extjs组件上
		'sqlinjectrulelist combobox[name=ruleSet]':
		{
			"addRuleSet": function()
			{
				alert('xxxxxxxxxxx');
				return true;
			}
		},	
//view中的组件如下:
			xtype : 'JComboBox', //自定义 继承自'Ext.form.field.ComboBox' 别名		alias: 'widget.JComboBox',
			fieldLabel : '规则集',
			name : 'ruleSet',
			id : 'ruleSet',
			editable : false,
			displayField : 'name',
			valueField : 'id',
			queryMode : 'remote',
			store : Ext.create('Ext.data.Store',{
				fields:['id','name'],
				autoLoad:true,
				proxy:{
					type:'ajax',
					url:'/JF/PolicyConfig_SqlInjectRule/getRuleSet',
				}
			}),				

发现一个问题:我的一个下拉列表第一次点击后,从远端获取完数据后,我的下拉列表又回缩了,之后,点击就没有该问题。

原因定位分析,发现是我代码的问题,我监听了 render事件,在这个组件渲染的时候绑定了store的load事件,之后我第一次点击下拉菜单,触发了load事件,这个时候我setValue让选择第一行就导致了我下拉框加载完突然回缩的问题。

listeners : {
		'render':function(combo){
			//store的load事件setValue第一行
			combo.getStore().on("load",function(s,r,o){
				console.log(r[0]);
				if(typeof r[0] != 'undefined'){
					//combo.setValue(r[0].get('id'));

				}else{
					combo.setValue('该对象无规则,请新建');							
				}
				s.add({id: '0',name: '--新建规则--'});});
		},

思路1:(推荐)
思考:发现下拉菜单comobox会在第一次点击下拉时,store会请求远端数据,但是页面在加载的时候,store已经ajax请求过了,combox中已经有值了,如何让有值得情况下,第一次点击下拉菜单不让store从服务器端ajax情况数据?

//竟然可以,你点击下拉的时候它不在会ajax请求了,只有在页面加载的那个时候才会ajax,或者你自己代码调load,解决了我的问题;

//queryMode : 'remote',
queryMode : 'local',
//完整代码
{
	xtype : 'JComboBox',
	fieldLabel : '规则集',
	name : 'ruleSet',
	id : 'ruleSet',
	editable : false,
	displayField : 'name',
	valueField : 'id',
	//queryMode : 'remote',
	queryMode : 'local',
	store : Ext.create('Ext.data.Store',{
		storeId:'ruleSetStore',
		fields:['id','name'],
		//autoLoad:false,
		autoLoad:true,
		proxy:{
			type:'ajax',
			url:'/JF/PolicyConfig_SqlInjectRule/getRuleSet',
		}
		/*
		listeners:{
			'load':function(){
				var record = this.getAt(0).get('id');
				Ext.getCmp('ruleSet').setValue(record);
			}
		}
		*/
	}),

思路2(失败):我直接在store 中配置load事件处理函数,然后setValue;结果一样,下拉列表还是会回缩。

store : Ext.create('Ext.data.Store',{
	fields:['id','name'],
	//autoLoad:false,
	autoLoad:false,
	proxy:{
		type:'ajax',
		url:'/JF/PolicyConfig_SqlInjectRule/getRuleSet',
	},
	listeners:{
		'load':function(){
			var record = this.getAt(0).get('id');
			Ext.getCmp('ruleSet').setValue(record);
		}
	}
}),

思路3:在combox组件的afterrender 事件中,setValue;理论上是可以的,但是我这里为什么查到的结果值都是null,所以set不上- -

'afterrender':function(combo){

	//var fLine = Ext.ComponentQuery.query('[name=ruleSet]')[0].value;  //null
	//var record =  this.getStore().getAt(0).get('id');
	//失败原因:这里this指向的下拉菜单组件,没有getStore方法
	//combo.setValue(fLine);
},

分析:原因处在对getStore 方法理解不到位,查验官方api学习之:

如下例子,一个窗口+表单,我在窗口的button组件中,使用this.getStore,要理解,你这里的this指向button对象,button对象就没有getStore方法。
之前在MVC开发中的 controlel中使用this.getStore 都是this指向当前的控制器control
查询官方api 关键字“getStore” 发现有Ext.getStore 有Ext.app.Controller.getStore Ext.app.ViewMode.getStorel等,说明在集成自控制器的才有该方法- -

因此,改用全局Ext.getStore,传参为storeId值,MVC开发模式下,就时控制器配置项stores实例化的store名。

getStore ( name ) : Ext.data.Store
Shortcut to Ext.data.StoreManager#lookup. Gets a registered Store by id
PARAMETERS
name : Object
RETURNS :Ext.data.Store

storeId : String BINDABLE
Unique identifier for this store. If present, this Store will be registered with the Ext.data.StoreManager, making it easy to reuse elsewhere.
Note that when a store is instantiated by a Controller, the storeId will default to the name of the store if not specified in the class.
Defaults to: null
storeId 是一个字符串,唯一的标识一个store。如果存在,这个store将被注册到store管理器,使其方便在其它地方复用。
注意当一个store被控制器实例化时,storeId将默认为这个store的名字(在类中没有定义的情况下)
这里就是这用情况,使用全局的Ext.getStore传进来的storeId就是控制器实例化的store。

			var dialog = Ext.create('Ext.window.Window', {
				title: '新建规则集',
				maxHeight: 400,
				name: 'add_cmd',
				width: 400,
				modal: true,
				constrainHeader: true,
				autoShow:true,
				items:[
				{ xtype: 'rulesetform' }
				],
				buttons:
				[
					{
						xtype:'JButton',
						text:'保存',
						minWidth:62,
						handler:function() {
							var me = this;
							var win = this.up('window');
							var form = win.down('form').getForm();
							//var store = Ext.getStore('SqlInjectRules');  错误点
							var store = Ext.getStore('SqlInjectRules');

//在store中,我是这样定义的
	Ext.define('JUMP.store.SqlInjectRules', {
		extend: 'Ext.data.Store',
		model: 'JUMP.model.SqlInjectRule',
		/*
		data: [
		
			{ name: 'HaMaster', level: '2', enable: 'up',baseling_name:'激活' },
			{ name: 'HaMaster', level: '1', enable: 'up',baseling_name:'激活' }
		]
		*/
		pageSize: 15,

总结:

  • 当你第一次点击下拉列表的时候,store就会触发ajax从远端获取数据,之后点击就不会触发store的ajax请求。 简单的说就是下拉菜单,第一次点击会触发store的load事件
  • getStore不是任何组件都有的,在control(this指向control对象)中可以直接用,其他组件的情况,可以采用全局Ext.getStore获得;
    传参为storeId值,MVC开发模式下,就时控制器配置项stores实例化的store名;
    其他情况下,给store添加配置项 storeId:‘xxx’,给store一个id

对下拉框组件的setValue的理解

displayField : 'name',
valueField : 'id',
//queryMode : 'remote',
queryMode : 'local',
store : Ext.create('Ext.data.Store',{
	storeId:'ruleSetStore',
	fields:['id','name'],

问题:有时你用setValue(key)方法赋值,但是发现,显示的是key不是key对应的value值。
setValue()的前提是combobox中的data已经被加载,如果没有该record,则直接显示key

思路1:这种情况,通常可以让下拉组件store load一下,重新从服务器端获取最新的数据,服务器端返回的数据按数据库中id降序排序,监听的store的load事件,这个时候在setValue第一行;这样的话,store中就有完整的信息,setValue就不会有问题。
Ext.getCmp(‘ruleSet’).getStore().load();

	listeners : {
			'render':function(combo){
				//store的load事件setValue第一行
				combo.getStore().on("load",function(s,r,o){
					//console.log(r[0]);
					if(typeof r[0] != 'undefined'){
						//for void list back 
						combo.setValue(r[0].get('id'));

					}else{
						combo.setValue('该对象无规则,请新建');							
					}
					s.add({id: '0',name: '--新建规则--'});});
			},

下拉列表添加一条选项到第一行

如上面的例子 操作store 使用 store的add添加到了下拉菜单的最后一行;有上面方法可以添加到第一行呢?

总结:

  • 下拉菜单一般两个字段displayField,valueField 你setValue set的是value值,它会自动显示display的值,前提你store有这个完整record,否则,你setValue什么就显示什么(这个时候你ajax请求提交的参数值也是你的setValue的值,会出现问题,你实际想提交的valueField中的值,但是此时,没有值)

所以,最佳实践就是 在record不完整的情况下,你想只是展示某个内容(不根据这个选择ajax情况),可以setValue;否则最好load一个完整的数据。

你可能感兴趣的:(extjs,前端)