しばらく頭を悩ませていたExtJsプロジェクトを開始しましたが、これは私を困惑させています。
リモート JSON ストアを使用してユーザーを一覧表示する Ext.form.ComboBox があります。ドロップダウンにリストされているように、XTemplate を使用してユーザーをフォーマットします。
'<tpl for="."><div class="x-combo-list-item">',
'{firstname} {lastname} ({email})',
'</div></tpl>'
ドロップダウンを展開すると、ユーザーが正しく一覧表示されます。
ジョン・スミス (jsmith@company.com)
ジョン・フォード (jford@company.com)
ただし、ユーザーをクリックすると、コンボ ボックスの内容が valueField プロパティ ('firstname') に変更されます。
問題:
John を表示する代わりに、コンボ ボックスに John Smith (jsmith@company.com) を表示したいと思います。
2 つの 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, id, 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);