I have already shown how to implement a Tree ComboBox. In the following example you can see how to implement a simpler ComboBox with a grid picker. It is implemented with support of the local and remote filtering. I have used also a calculated model field ‘fullName’ to use it as display value in the combo. You can also use as ‘displayTpl’ property to achieve the same effect.
The filter property, the model field name which is used to filter data is defined in ‘filterField’ setting of theComboBox.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
Ext.define('app.ux.form.field.GridComboBox', { extend: 'Ext.form.field.Picker', requires: [ 'app.ux.form.field.GridComboBoxList' ], store: false, queryMode: 'local', anyMatch: false, filterDelayBuffer: 300, enableKeyEvents: true, valueField: 'text', selectedRecord: false, gridConfig: { // Grid Config }, initComponent: function () { this.on('change', this.onGridComboValueChange, this, { buffer: this.filterDelayBuffer }); this.on('keydown', this.onItemKeyDown, this, { buffer: this.filterDelayBuffer }); this.callParent(); }, onGridComboValueChange: function (field, value) { this.selectedRecord = false; switch (this.queryMode) { case 'local': this.getPicker().doLocalQuery(value) break; case 'remote': this.getPicker().doRemoteQuery(value); break; } }, onItemKeyDown: function() { this.expand(); }, expand: function () { this.callParent([arguments]); }, createPicker: function () { var gridConfig = Ext.apply({ xtype: 'gridcomboboxlist', id: this.getId() + '-GridPicker', store: this.getPickerStore(), valueField: this.valueField, displayField: this.displayField, anyMatch: this.anyMatch, allowFolderSelect: this.allowFolderSelect, columns: this.columns, filterField: this.filterField }, this.gridConfig); var gridPanelPicker = Ext.widget(gridConfig); gridPanelPicker.on({ picked: this.onPicked, filtered: this.onFiltered, beforeselect: this.onBeforeSelect, beforedeselect: this.onBeforeDeselect, scope: this }); return gridPanelPicker; }, onFiltered: function (store, gridList) { if (store.getCount() > 0) { this.focus(); } }, getPickerStore: function () { return this.store; }, onPicked: function (record) { this.suspendEvent('change'); this.selectedRecord = record; this.setValue(record.get(this.displayField)); this.collapse(); this.resumeEvent('change'); this.fireEvent('select', record); }, getValue: function () { var value; if (this.valueField && this.selectedRecord) { value = this.selectedRecord.get(this.valueField); } else { value = this.getRawValue(); } return value; }, getSubmitValue: function () { var value = this.getValue(); if (Ext.isEmpty(value)) { value = ''; } return value; }, onBeforeSelect: function (comboBox, record, recordIndex) { return this.fireEvent('beforeselect', this, record, recordIndex); }, onBeforeDeselect: function (comboBox, record, recordIndex) { return this.fireEvent('beforedeselect', this, record, recordIndex); }, getSelectedRecord: function () { return this.selectedRecord; } }); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
Ext.define('app.ux.form.field.GridComboBoxList', { extend: 'Ext.grid.Panel', alias: 'widget.gridcomboboxlist', floating: true, hidden: true, value: false, anyMatch: false, initComponent: function () { this.listeners = { 'cellclick': this.onCellClick, 'itemkeydown': this.onItemKeyDown }; this.callParent(); }, onCellClick: function (tree, td, cellIndex, record, tr, rowIndex, e, eOpts) { this.fireEvent('picked', record); }, onItemKeyDown: function (view, record, item, index, e, eOpts) { if (e.keyCode == e.ENTER) { this.fireEvent('picked', record); } }, selectFirstRow: function () { var firstRecord = this.getStore().getAt(0); this.getSelectionModel().select(firstRecord); }, doLocalQuery: function (searchValue) { var store = this.getStore(); this.searchValue = searchValue.toLowerCase(); store.setRemoteFilter(false); store.filterBy(this.pickerStoreFilter, this); this.fireEvent('filtered', store, this); }, pickerStoreFilter: function (record) { var itemValue = record.get(this.filterField).toLowerCase(); if (this.anyMatch) { if (itemValue.indexOf(this.searchValue) != -1) { return true; } } else { if (itemValue.startsWith(this.searchValue)) { return true; } } return false; }, doRemoteQuery: function (searchValue) { var store = this.getStore(); store.setRemoteFilter(true); store.on('load', this.onPickerStoreLoad, this, { single: true }); store.filter(new Ext.util.Filter({ anyMatch: this.anyMatch, disableOnEmpty: true, property: this.filterField, value: searchValue })); }, onPickerStoreLoad: function (store, records) { this.fireEvent('filtered', store, this); } }); |
In the following fiddle I have used the ‘app.view.cmp.employees.ComboBox’ class to not define the same column model for two remote and local filtering comboboxes.