ExtJS EditorGridPanel 中的级联组合框

发布于 2024-09-28 04:41:15 字数 509 浏览 3 评论 0原文

我有一个正在运行的 EditorGrid 面板,其中两列有 ComboBox 编辑器。两个 ComboBox 都是从数据库(countryStorecityStore)远程加载的。

我想限制 cityComboBox 仅显示所选国家/地区的城市。我需要使用数据库中的过滤器重新加载 cityStore (有太多城市无法过滤本地)。过滤器值是 countryComboBox 值。

CountryComboBox 中始终有一个值,因为我在创建新记录时添加了 default = 1,所以这不是问题。

我不知道哪个听众适合这里。我需要在 countryComboBox 显示之前捕捉双击国家/地区单元格的时刻,并在组合框显示之前对其进行过滤(或在检索数据时显示等待消息)。

如果这是不可能的,我可以通过双击单元格打开弹出窗口,从过滤城市的组合框中选择,“确认”并将值输入单元格吗?

I have a working EditorGrid panel, where two columns have ComboBox editors. Both ComboBoxes are loaded remotely from database (countryStore and cityStore).

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.

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

真心难拥有 2024-10-05 04:41:15

我终于成功了。我创建了两个解决方案 - 用于网格内的本地和远程下拉搜索。最后,我决定使用本地搜索(我可以将 country_id 添加到我的 cities 查询中并在 ExtJS 中进行过滤),但也可以使其适用于远程搜索- 如果有人需要,我也可以准备该解决方案。

LOCAL SOLUTION

我必须使用 beforeQuery 事件过滤 cityCombo,并使用同一行中 countryCombo 的 id。这是 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 具有以下字段: idcountry_idcity

仍然存在一个问题:当用户更改时在countryCombo中,城市字段应该更改/警告用户它对于当前国家/地区不正确。这个问题的解决方案很复杂......你可能知道,你无法获得对组合框的parentGrid的引用(否则你可以调用countryCombo --> ParentGrid --> currentRecord --> cityCombo -- >改变它)。

我尝试监听网格本身的 rowchange 事件,但是如果用户在更改 countryCombo 后直接单击另一行,则会更改错误的行城市。

该解决方案有些高级:我必须将当前行的引用从网格的 beforeedit 事件复制到 cityCombo。这是网格的侦听器:

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 代码:

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)。

远程解决方案要求我为城市创建两个商店 - cityRendererStorecityDropdownStore,它们每次都会查询数据库而不是使用过滤器。如果您有太多城市需要进行本地过滤,则这种方法是必要的。我应该提到我并没有在我的应用程序中真正使用城市和国家,我只是创建这个示例来简化事情。

我对最终结果感到非常高兴 - 它提供了网格的所有优点以及通常仅在表单中可用的条件下拉菜单。

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.

LOCAL SOLUTION

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

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

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).

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.

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

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

    }
});

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).

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.

与酒说心事 2024-10-05 04:41:15

我可以在这里看到几个选项。您可以捕获商店的 update 事件(当基础记录更新或标记为脏时)或捕获countryComboBox 的select 事件。这两者都会为您提供所选国家/地区的 id 值,然后您可以将其添加到 cityComboBox 的 baseParams 中以进行远程过滤。

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文