我有一个Ext.form.ComboBox,它使用远程JSON存储来列出用户.我使用XTemplate格式化下拉列表中列出的用户:
'<tpl for="."><div class="x-combo-list-item">','{firstname} {lastname} ({email})','</div></tpl>'
当我展开下拉列表时,我看到我的用户列出正确:
约翰史密斯(jsmith@company.com)
约翰福特(jford@company.com)
但是,当我单击用户时,组合框内容将更改为您期望的valueField属性(‘firstname’).
问题:
>而不是展示约翰,我想要显示组合框:John Smith(jsmith@company.com).
>当我有两个John(John Smith和John Ford)并加载表单时,ExtJs逻辑与它在列表中找到的第一个John匹配,并将该字段的值更改为它匹配的第一个John.
例如:
约翰史密斯(ID = 1)
约翰福特(ID = 2)
用户选择John Ford,并且在他们单击组合菜单项后,“John”出现在组合框中,并且user_id = 2被写入数据库.
然而,当我重新加载页面时,名称“John”匹配(从数据库加载)到第一个列表条目,如果运算符没有在下拉对话框中手动更改选择,则选择John Smith并且user_id =现在将1写入数据库(当用户保存表单时).
任何输入都将非常感激.我的直觉告诉我在加载和发布列表单击期间应该有几个钩子,这将允许我操作写入元素的innerHTML元素的内容.
~~~~~~~~~~~~~
注意:我继承了一个自定义类,它允许我提前输入查询,名字,姓氏和电子邮件地址(因为我们可能有数百个用户要搜索).
我继承的ComboBox元素:
CW.form.CustomComboBox = Ext.extend( Ext.form.ComboBox,{ filterKeys:[],// Note: This overrides the standard doQuery function in Ext 3.3 doQuery: function(q,forceAll){ q = Ext.isEmpty(q) ? '' : q; var qe = { query: q,forceAll: forceAll,combo: this,cancel:false }; if(this.fireEvent('beforequery',qe)===false || qe.cancel){ return false; } q = qe.query; forceAll = qe.forceAll; if(forceAll === true || (q.length >= this.minChars)){ if(this.lastQuery !== q){ this.lastQuery = q; if(this.mode == 'local'){ this.selectedIndex = -1; if(forceAll){ this.store.clearFilter(); }else{ // this.store.filter(this.displayField,q); this.store.filterBy( function(rec,id){ return this.filterFn(rec,id,q); },this ); } this.onLoad(); }else{ this.store.baseParams[this.queryParam] = q; this.store.load({ params: this.getParams(q) }); this.expand(); } }else{ this.selectedIndex = -1; this.onLoad(); } } },/** * Custom function for filtering the store */ filterFn: function(rec,q ){ // var filterKeys = ['id','firstname','lastname','email']; var parts = q.split(' '); // If no filter applied then show no results if(parts.length == 0){ return false; } // Iterate through each of the parts of the user string // They must all match,at least in part,one of the filterKeys // (i.e. id,email,firstname,etc.) for(i=0; i<parts.length;i++){ var foundPart = false; // Create a RegExp object for this search snippet (i.e. '@gmai') var matcher = this.store.data.createValueMatcher(parts[i],true); // Search until this matches one of the keys for this record for(j=0;j<this.filterKeys.length; j++){ if(matcher.test(rec.get(this.filterKeys[j]))){ foundPart = true; break; } } // If there are no fields of the record matching this part,// the record does not match (return false) if( foundPart == false ){ return false; } } return true; },initComponent: function(){ Ext.applyIf(this,{ listeners:{ beforequery: function(qe){ delete qe.combo.lastQuery; return true; } } }); if(this.filterKeys.length == 0){ this.filterKeys = [this.displayField]; } CW.form.CustomComboBox.superclass.initComponent.call(this); } }); Ext.reg('custom-combo',CW.form.CustomComboBox);
解决方法
var store = new Ext.data.ArrayStore({ fields: ['abbr','state','nick',{ name: 'display',convert: function(v,rec) { return rec[1] +' - '+ rec[0] } // display looks like 'Texas - TX' }],data : Ext.exampledata.states // from states.js }); var combo = new Ext.form.ComboBox({ store: store,displayField:'display',typeAhead: true,mode: 'local',forceSelection: true,triggerAction: 'all',emptyText:'Select a state...',selectOnFocus:true,applyTo: 'local-states' });
现在,组合显示的值如德克萨斯 – 德克萨斯州,或任何你转换输出的值.您可以在Ext.data.Field docs中找到转换文档.
对于问题#2,如果您正在使用JsonStore或ArrayStore等方便的商店阅读器组合之一,则可能需要为Ext.data.Reader或商店设置idProperty. idProperty告诉Ext哪个字段要查找唯一标识符.如果您没有idProperty或者选择一个不唯一的行为,您可以获得各种奇怪的行为.文件是here.