ExtJS EditorGridPanel 中的级联组合框 [英] Cascading ComboBoxes in ExtJS EditorGridPanel
问题描述
我有一个可以工作的 EditorGrid 面板,其中两列有 ComboBox 编辑器.两个 ComboBox 都是从数据库(countryStore
和 cityStore
)远程加载的.
I have a working EditorGrid panel, where two columns have ComboBox editors. Both ComboBoxes are loaded remotely from database (countryStore
and cityStore
).
我想将 cityComboBox
限制为仅显示所选国家/地区的城市.我需要使用数据库中的过滤器重新加载 cityStore
(有太多城市需要过滤本地).过滤器值为 countryComboBox
值.
I would like to limit the cityComboBox
to show only cities in the selected country. I need to reload the cityStore
with a filter from database (there are too many cities to filter localy). The filter value is the countryComboBox
value.
countryComboBox 里总有一个值,因为我在新建记录的时候加了一个default=1,所以这不是问题.
There is always a value in countryComboBox, because I add a default = 1 when creating a new record, so this isn't a problem.
我不知道哪个听众适合这里.我需要抓住在 countryComboBox
出现之前双击国家/地区单元格的时刻,并在组合框显示之前对其进行过滤(或在检索数据时显示等待消息).
I don't know which listener would be appropriate here. I need to catch the moment when I double click on the country cell, before the countryComboBox
shows up and filter the combo box before it's shown (or display a waiting message while it's retrieving data).
如果这是不可能的,我可以通过双击一个单元格来打开一个弹出窗口,从过滤城市的组合框中选择,确认"并在单元格中输入值?
If this is not possible, could I open a popup window by double clicking a cell, choose from a comboBox of filtered cities, "confirm" and enter the value into the cell?
推荐答案
我终于成功了.我创建了两个解决方案 - 用于网格内的本地和远程下拉搜索.最后,我决定使用本地搜索(我可以将 country_id
添加到我的 cities
查询和 ExtJS 中的过滤器),但可以使其适用于远程搜索- 如果有人需要,我也可以准备该解决方案.
I finally made it work. I created two solutions - for local and remote dropdown searches within the grid. In the end, I decided to use a local search (I can add country_id
to my cities
query and filter in ExtJS), but it's possible to make this work for remote searches - if anyone needs that, I can prepare that solution too.
本地解决方案
我必须使用 beforeQuery 事件过滤 cityCombo
,在同一行中使用来自 countryCombo
的 id.这是 cityCombo
的代码:
I had to filter cityCombo
using a beforeQuery event, using the id from countryCombo
in the same row. Here's 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 } );
}
}
});
如您所见,当双击网格内的 cityCombo
时,我会在当前行中获取 country_id
并使用过滤器 cityStore
那个值.这需要 cityStore
具有以下字段: id
, country_id
, city
As you can see, when the cityCombo
inside the grid is double clicked, I get country_id
in the current row and filter cityStore
using that value. This requires cityStore
to have these fields: id
, country_id
, city
仍然存在一个问题:当用户更改countryCombo
时,城市字段应该更改/警告用户它不适合当前国家/地区.对此的解决方案很复杂……正如您所知,您无法获得对组合框的 parentGrid 的引用(否则您只需调用 countryCombo --> parentGrid --> currentRecord --> cityCombo --> 改变它
).
One problem still remains: when the user changes the countryCombo
, the city field should change / warn the user that it's not correct for the current country. The solution for this was complicated... as you may know, you cannot get a reference to a comboBox's parentGrid (otherwise you could just call countryCombo --> parentGrid --> currentRecord --> cityCombo --> change it
).
我尝试在网格本身上监听 rowchange 事件,但是如果用户在更改 countryCombo
后直接单击另一行,则会更改错误的行所在城市.
I tried listening to the rowchange event on the grid itself, but if a user clicked to another row directly after changing countryCombo
, it changed the wrong row's city.
解决方案有些先进:我必须将当前行的引用从网格的 beforeedit 事件复制到 cityCombo.这是网格的监听器:
The solution was somewhat advanced: I had to copy references for current row to cityCombo from the grid's beforeedit event. Here's the grid's 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');
}
}
},
现在我们的 countryCombo
拥有在城市发生变化时重置城市所需的所有信息.这是整个 countryCombo
代码:
Now our countryCombo
has all the information neccessary to reset the city when it gets changed. Here's 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');
}
}
});
单元渲染器对我过滤他们的商店没有问题,所以我只需要一个商店来进行渲染和组合框编辑 (cityStore).
Cell renderers didn't have a problem with me filtering their store, so I only needed one store for both rendering and comboBox editing (cityStore).
远程解决方案要求我为城市创建两个商店 - cityRendererStore
和 cityDropdownStore
,它们每次都查询数据库而不是使用过滤器.如果您有太多城市需要在本地进行过滤,那么这种方法是必要的.我应该提到我在我的应用程序中并没有真正使用城市和国家,我只是创建了这个例子来简化事情.
The remote solution required me to create two stores for cities - cityRendererStore
and cityDropdownStore
, which queried the database each time instead of using filters. That approach is neccessary if you have too many cities to filter locally. I should mention I'm not really using cities and countries in my application, I just created this example to simplify things.
我对最终结果非常满意 - 它提供了网格的所有优点以及通常仅在表单中可用的条件下拉菜单.
I'm really happy about the end result - it gives all the benefits of a grid together with conditional dropdowns usually available only in forms.
这篇关于ExtJS EditorGridPanel 中的级联组合框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!