Cascading ComboBoxes in ExtJS EditorGridPanel

I have an EditorGrid dashboard where two columns have ComboBox editors. Both ComboBoxes are loaded remotely from the database ( countryStore and cityStore ).

I would like to restrict cityComboBox displaying only cities in the selected country. I need to reload cityStore using a filter from the database (there are too many cities to filter locally). The filter value is the value of countryComboBox .

There is always a value in countryComboBox because I add the default value = 1 when creating a new record, so this is not a problem.

I do not know which listener would be appropriate here. I need to catch the moment when I double-click on a country cell, before countryComboBox and filters out the combo box before showing it (or displays a pending message when retrieving data).

If this is not possible, can I open a pop-up window by double-clicking on a cell, select filtered cities from comboBox, "confirm" and enter a value in the cell?

+4
source share
2 answers

I finally earned it. I created two solutions - for local and remote search in the grid. In the end, I decided to use local search (I can add country_id to my cities query and filter in ExtJS), but this work can be done for remote searches - if someone needs it, I can prepare this solution too.

LOCAL SOLUTION

I had to filter cityCombo using the beforeQuery event, using the id from countryCombo on the same line. Here is the code for cityCombo :

 var cityCombo = new Ext.form.ComboBox({ triggerAction: 'all', mode: 'local', lastQuery: '', // to make sure the filter in the store is not cleared the first time the ComboBox trigger is used store: cityDropdownStore, displayField: 'city', valueField: 'city_id', listeners: { beforeQuery: function(query) { currentRowId = myGrid.getSelectionModel().getSelected().data.country_id; this.store.clearFilter(); this.store.filter( { property: 'country_id', value: currentRowId, exactMatch: true } ); } } }); 

As you can see, when I double-click cityCombo inside the grid, I get the country_id in the current row and the cityStore filter using this value. This requires cityStore have the following fields: id , country_id , city

Another problem remains: when the user changes the countryCombo , the city field should change / warn the user that it does not correspond to the current country. The solution for this was complicated ... as you probably know, you cannot get a link to comboBox parentGrid (otherwise you could just call countryCombo --> parentGrid --> currentRecord --> cityCombo --> change it ).

I tried to listen for the rowchange event in the grid itself, but if the user clicked on another line right after changing countryCombo , he changed the wrong city of lines.

The solution was somewhat advanced: I had to copy the links for the current line in cityCombo from the gridededed event. Here's the grid listener for this:

 listeners: { beforeedit: function(e) { // reference to the currently clicked cell var ed = e.grid.getColumnModel().getCellEditor(e.column, e.row); if (ed && ed.field) { // copy these references to the current editor (countryCombo in our case) Ext.copyTo(ed.field, e, 'grid,record,field,row,column'); } } }, 

Now our countryCombo has all the information necessary to reset the city when it changes. Here is the whole countryCombo code:

 var countryCombo = new Ext.form.ComboBox({ id: 'skupina_combo', typeAhead: true, triggerAction: 'all', lazyRender: true, mode: 'local', store: countryDropdownStore, displayField: 'country', valueField: 'country_id', listeners: { change: function(t, n, o) { // t is the reference to the combo // I have t.record available only because I copied it in the beforeEdit event from grid t.record.set('city_id', '0'); } } }); 

The cell handlers had no problems filtering their storage, so I needed only one storage to render and edit comboBox (cityStore).

The remote solution required me to create two stores for cities - cityRendererStore and cityDropdownStore , which each time requested a database, rather than using filters. This approach is necessary if you have too many cities to filter locally. I should mention that I do not use cities and countries in my application, I just created this example to simplify.

I am really pleased with the end result - it gives all the advantages of the grid along with conditional drop-down lists, usually available only in forms.

+5
source

Here I see a couple of options. You can catch the store update event (when the base record is updated or marked dirty) or catch the countryComboBox select event. Both of them will provide you with the id value of the selected country, which you can then add to your cityComboBox baseParams for remote filtering.

+1
source

All Articles