I opened an ExtJs project in which I did not have a head yet, and that puzzles me.
I have an Ext.form.ComboBox that uses a remote JSON store to list users. I use XTemplate to format the users listed in the drop-down list:
'<tpl for="."><div class="x-combo-list-item">', '{firstname} {lastname} ({email})', '</div></tpl>'
When I expand the drop-down list, I see that my users are listed correctly:
John Smith ( jsmith@company.com )
John Ford ( jford@company.com )
However, when I click on the user, the contents of the combo box changes to the valueField ('firstname') property that you expect.
Questions:
Instead of showing John, I would like the combo box to show: John Smith ( jsmith@company.com ).
When I have two John (John Smith and John Ford) and upload the form, the ExtJs logic matches the first John that he finds on the list and changes the field value to the first John that he matches against.
For example: John Smith (ID = 1) John Ford (ID = 2)
The user selects John Ford, and βJohnβ appears in the combo box after he clicked on the combo menu item, and user_id = 2 is written to the database.
However, when I reload the page, the name "John" is mapped (loaded from the database) into the first entry of the list, and if the operator does not manually change the selection in the pop-up dialog box, John Smith is selected and user_id = 1 is now written to the database (when the user retains shape).
Any input would be greatly appreciated. My gut tells me that while loading and clicking the message list there should be several hooks that will allow me to manipulate what is written in the element's innerHTML element.
~~~~~~~~~~~~~
Note. I inherited from a user class that allows me to type the query forward, first name, last name and email address (since we can potentially have hundreds of users to search for).
ComboBox element inherited by me:
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 // (ie id, email, firstname, etc.) for(i=0; i<parts.length;i++){ var foundPart = false; // Create a RegExp object for this search snippet (ie '@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);