Display multiple fields in ExtJs 3.3 Combo box

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); 
+6
source share
2 answers

As for problem # 1, the best way I found to get good custom display fields is to use the generated fields in the Ext.data.Record definition that the Store uses. Thus, you get a full record for access to create a display field and are not limited to only one field. I can’t find 3.x examples on the Internet right now when Sencha goes to Ext4, but this example can be found in the examples/form directory of your ExtJS download. Here I changed one of ExtJS compilation examples/form/combo.js ( examples/form/combo.js ):

 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' }); 

And now the combo displays values ​​like Texas - TX , or whatever you have convert . You can find the documentation for convert in Ext.data.Field Docs .

As for problem # 2, you may need to install idProperty for your Ext.data.Reader or your store if you use one of the convenient store + reader combines, such as JsonStore or ArrayStore. idProperty tells Ext in which field to look for a unique identifier. You can get all kinds of weird behavior if you don't have idProperty or you choose one that is not unique. The docs for this are here .

+10
source

You just need to replace your displayField with the code below

 tpl: Ext.create('Ext.XTemplate', '<tpl for=".">', '<div class="x-boundlist-item">{firstName} {lastName} {email}</div>', '</tpl>' ), // template for the content inside text field displayTpl: Ext.create('Ext.XTemplate', '<tpl for=".">', 'firstName} {lastName} {email}', '</tpl>' ) 
+2
source

Source: https://habr.com/ru/post/887146/


All Articles