如何在编辑器网格面板内呈现远程组合框的初始显示值?

问题描述

注意:我最近发布了 this question,它询问了一个简单的远程组合框。这个问题类似但不重复,因为它将远程组合放在远程网格中。

我正在渲染一个 EditorGridPanel。其中一列使用 ComboBox 编辑器。网格和组合框从不同的 HTTP 端点加载各自的数据。如何强制组合列在初始加载时呈现显示字段?

我找到了一些解决方法,但似乎应该有更简单的方法。我的解决方法基本上是强制这些异步加载同步:首先加载组合存储,然后加载网格存储。例如,如果我在单个网格中有多个远程组合,这会变得复杂。底层数据改变后,有没有办法强制combo重新渲染?

这是一个例子。您可以将此代码放在任何 ExtJS 3.4 Fiddle 中。

// Create a remote store for the combo Box.
var remoteStore = new Ext.data.JsonStore({
    url: 'https://jsonplaceholder.typicode.com/todos',autoLoad: true,fields: ['id','title']
});

// Create the combo Box.
var remoteCombo = new Ext.form.ComboBox({
    fieldLabel: 'Remote Store (busted)',triggerAction: 'all',mode: 'local',store: remoteStore,valueField: 'id',displayField: 'title',lazyRender: true
});

// Create the column model for the grid.
var columnModel = new Ext.grid.ColumnModel(
    [{
        header: 'Column 1',dataIndex: 'column1',width: 220,editor: new Ext.form.TextField()
    },{
        id: 'column2',header: 'Column 2',dataIndex: 'column2',width: 130,editor: remoteCombo,renderer: (value) => {
            var record = remoteCombo.findRecord(remoteCombo.valueField,value);
            return record ? record.get(remoteCombo.displayField) : 'Loading...';
        }
    }]
);

// Create a local grid store with some fake data.
var fakeData = [{
    column1: 'row 1',column2: 1
},{
    column1: 'row 2',column2: '2'
},{
    column1: 'row 3',column2: '3'
}];
var gridStore = new Ext.data.JsonStore({
    autoDestroy: true,autoLoad: false,fields: ['column1','column2'],data: fakeData
});

// Workaround #1: load grid store AFTER all required combo stores are loaded.
// remoteStore.on('load',() => gridStore.loadData(fakeData));

// Workaround #2: force the column to re-render all records after the store is loaded.
// Kludgy and also marks the records as dirty.
// remoteStore.on('load',() => {
//     gridStore.each((record) => {
//         var originalValue = record.get('column2');
//         record.set('column2',undefined);
//         record.set('column2',originalValue);
//     });
// });

// Render the grid.
new Ext.grid.EditorGridPanel({
    store: gridStore,cm: columnModel,autoExpandColumn: 'column2',renderTo: Ext.getBody(),width: 600,height: 300,title: 'Grid with remote combo',frame: true,});

解决方法

我认为您可以避免商店的同步加载。只需将 remoteStore 'load' 事件的单个侦听器放在网格 'render' 事件中。像这样:

// Create a remote store for the combo box.
var remoteStore = new Ext.data.JsonStore({
    url: 'https://jsonplaceholder.typicode.com/todos',autoLoad: true,fields: ['id','title']
});

// Create the combo box.
var remoteCombo = new Ext.form.ComboBox({
    fieldLabel: 'Remote Store (busted)',triggerAction: 'all',mode: 'local',store: remoteStore,valueField: 'id',displayField: 'title',lazyRender: true
});

// Create the column model for the grid.
var columnModel = new Ext.grid.ColumnModel(
    [{
        header: 'Column 1',dataIndex: 'column1',width: 220,editor: new Ext.form.TextField()
    },{
        id: 'column2',header: 'Column 2',dataIndex: 'column2',width: 130,editor: remoteCombo,renderer: (value,metaData,record,rowIndex,colIndex,store) => {
            var recordIndex = remoteCombo.getStore().findExact(remoteCombo.valueField,value);
            var record = remoteCombo.getStore().getAt(recordIndex);
            return record ? record.get(remoteCombo.displayField) : 'Loading...';
        }
    }]
);

// Create a local grid store with some fake data.
var fakeData = [{
    column1: 'row 1',column2: 1
},{
    column1: 'row 2',column2: 2
},{
    column1: 'row 3',column2: 3
}];
var gridStore = new Ext.data.JsonStore({
    autoDestroy: true,autoLoad: false,fields: ['column1','column2'],data: fakeData
});

// Workaround #1: load grid store AFTER all required combo stores are loaded.
// remoteStore.on('load',() => gridStore.loadData(fakeData));

// Workaround #2: force the column to re-render all records after the store is loaded.
// Kludgy and also marks the records as dirty.
// remoteStore.on('load',() => {
//     gridStore.each((record) => {
//         var originalValue = record.get('column2');
//         record.set('column2',undefined);
//         record.set('column2',originalValue);
//     });
// });

// Render the grid.
new Ext.grid.EditorGridPanel({
    store: gridStore,cm: columnModel,autoExpandColumn: 'column2',renderTo: Ext.getBody(),width: 600,height: 300,title: 'Grid with remote combo',frame: true,listeners: {
        render: function (grid) {
            if (remoteStore.lastOptions === null) {
                remoteStore.on('load',function (store) {
                    grid.getView().refresh();
                },this,{
                    single: true
                });
            }
        }
    }
});

附言 我已经修复了渲染器。 P.P.S.小心 findExact 的字符串和整数值。AFAIK 它是类型敏感的方法。