6

细节

我有一个用于显示发票信息的网格。使用 Invoice 存储填充网格,Invoice 存储使用 Invoice 模型,Invoice 模型与 InvoiceStatus 模型具有“具有一个”关联,主键为“id”,前键为“invoice_status_id”。

问题

我不确定如何使 Invoice Grid 的“Status”列的显示值使用插入 invoice_status_id 的关联模型“name”。我知道我需要创建一个渲染器来执行此操作,但是我仍然得到一个空值。Invoice 和 InvoiceStatus 存储都填充了正确的值。

状态列渲染

renderer: function(value, metaData, record, rowIndex, colIndex, store, view) {
    return record.getStatus().get('name');
},

发票商店

Ext.define('MyApp.store.Invoice', {
    extend: 'Ext.data.Store',

    requires: [
        'MyApp.model.InvoiceModel'
    ],

    constructor: function(cfg) {
        var me = this;
        cfg = cfg || {};
        me.callParent([Ext.apply({
            autoLoad: true,
            autoSync: true,
            model: 'MyApp.model.InvoiceModel',
            remoteSort: true,
            storeId: 'StoreInvoce',
            proxy: {
                type: 'rest',
                url: '/api/invoice',
                reader: {
                    type: 'json',
                    root: 'data'
                }
            }
        }, cfg)]);
    }
});

发票状态存储

Ext.define('MyApp.store.InvoiceStatus', {
    extend: 'Ext.data.Store',
    alias: 'store.InvoiceStatus',

    requires: [
        'MyApp.model.InvoiceStatus'
    ],

    constructor: function(cfg) {
        var me = this;
        cfg = cfg || {};
        me.callParent([Ext.apply({
            autoLoad: true,
            autoSync: true,
            model: 'MyApp.model.InvoiceStatus',
            remoteSort: true,
            storeId: 'MyJsonStore1',
            proxy: {
                type: 'rest',
                url: '/api/invoice_status',
                reader: {
                    type: 'json',
                    root: 'data'
                }
            }
        }, cfg)]);
    }
});

发票型号

Ext.define('MyApp.model.InvoiceModel', {
    extend: 'Ext.data.Model',
 
    uses: [
        'MyApp.model.InvoiceStatus'
    ],
 
    fields: [
        {
            mapping: 'id',
            name: 'id',
            type: 'int'
        },
        {
            mapping: 'client_id',
            name: 'client_id',
            type: 'int'
        },
        {
            mapping: 'client_name',
            name: 'client_name',
            type: 'string'
        },
        {
            dateFormat: 'Y-m-d',
            dateReadFormat: '',
            mapping: 'issue_date',
            name: 'issue_date',
            sortType: 'asDate',
            type: 'date'
        },
        {
            dateFormat: 'Y-m-d',
            mapping: 'due_date',
            name: 'due_date',
            sortType: 'asDate',
            type: 'date'
        },
        {
            mapping: 'payment_date',
            name: 'payment_date',
            sortType: 'asDate',
            type: 'date',
            useNull: true
        },
        {
            name: 'amount'
        },
        {
            mapping: 'invoice_status_id',
            name: 'invoice_status_id',
            sortType: 'asInt',
            type: 'int'
        }
    ],
 
    hasOne: {
        model: 'MyApp.model.InvoiceStatus',
        foreignKey: 'invoice_status_id',
        getterName: 'getStatus'
    }
});

发票状态模型

Ext.define('MyApp.model.InvoiceStatus', {
    extend: 'Ext.data.Model',

    fields: [
        {
            mapping: 'id',
            name: 'id',
            type: 'int'
        },
        {
            mapping: 'name',
            name: 'name',
            type: 'string'
        }
    ]
});

发票网格

Ext.define('MyApp.view.ApplicationViewport', {
    extend: 'Ext.container.Viewport',

    requires: [
        'MyApp.view.ClearTriggerField'
    ],

    layout: {
        type: 'border'
    },

    initComponent: function() {
        var me = this;

        Ext.applyIf(me, {
            items: [
                {
                    xtype: 'header',
                    region: 'north',
                    height: 100,
                    items: [
                        {
                            xtype: 'image',
                            height: 100,
                            width: 250,
                            alt: 'Logo',
                            src: 'images/logo.gif',
                            title: 'Logo'
                        }
                    ]
                },
                {
                    xtype: 'container',
                    region: 'center',
                    layout: {
                        type: 'card'
                    },
                    items: [
                        {
                            xtype: 'container',
                            width: 150,
                            layout: {
                                type: 'border'
                            },
                            items: [
                                {
                                    xtype: 'gridpanel',
                                    collapseMode: 'mini',
                                    region: 'west',
                                    split: true,
                                    autoRender: false,
                                    maxWidth: 300,
                                    width: 250,
                                    bodyBorder: false,
                                    animCollapse: false,
                                    collapsed: false,
                                    collapsible: true,
                                    hideCollapseTool: true,
                                    overlapHeader: false,
                                    titleCollapse: true,
                                    allowDeselect: true,
                                    columnLines: false,
                                    forceFit: true,
                                    store: 'ClientDataStor',
                                    dockedItems: [
                                        {
                                            xtype: 'toolbar',
                                            dock: 'top',
                                            items: [
                                                {
                                                    xtype: 'cleartrigger'
                                                },
                                                {
                                                    xtype: 'tbfill'
                                                },
                                                {
                                                    xtype: 'button',
                                                    icon: '/images/settings.png'
                                                }
                                            ]
                                        }
                                    ],
                                    columns: [
                                        {
                                            xtype: 'templatecolumn',
                                            tpl: [
                                                '<img class="pull-left client-menu-image" src="/images/{type}.png"><div class="client-menu-name">{name}</div><div class="client-menu-type">{type}</div>'
                                            ],
                                            dataIndex: 'id',
                                            text: 'Client'
                                        }
                                    ],
                                    selModel: Ext.create('Ext.selection.RowModel', {

                                    }),
                                    plugins: [
                                        Ext.create('Ext.grid.plugin.BufferedRenderer', {

                                        })
                                    ]
                                },
                                {
                                    xtype: 'gridpanel',
                                    region: 'center',
                                    title: 'Invoices',
                                    titleCollapse: false,
                                    forceFit: true,
                                    store: 'Invoice',
                                    columns: [
                                        {
                                            xtype: 'numbercolumn',
                                            maxWidth: 120,
                                            minWidth: 50,
                                            dataIndex: 'id',
                                            groupable: false,
                                            lockable: true,
                                            text: 'ID',
                                            tooltip: 'Invoice ID',
                                            format: '0'
                                        },
                                        {
                                            xtype: 'numbercolumn',
                                            hidden: true,
                                            maxWidth: 120,
                                            minWidth: 50,
                                            dataIndex: 'client_id',
                                            groupable: true,
                                            text: 'Client ID',
                                            format: '0'
                                        },
                                        {
                                            xtype: 'gridcolumn',
                                            renderer: function(value, metaData, record, rowIndex, colIndex, store, view) {
                                                return record.getStatus().get('name');
                                            },
                                            maxWidth: 200,
                                            minWidth: 100,
                                            dataIndex: 'invoice_status_id',
                                            text: 'Status'
                                        },
                                        {
                                            xtype: 'datecolumn',
                                            maxWidth: 200,
                                            minWidth: 100,
                                            dataIndex: 'issue_date',
                                            text: 'Issue Date',
                                            format: 'd M Y'
                                        },
                                        {
                                            xtype: 'datecolumn',
                                            maxWidth: 200,
                                            minWidth: 100,
                                            dataIndex: 'due_date',
                                            text: 'Due Date',
                                            format: 'd M Y'
                                        },
                                        {
                                            xtype: 'datecolumn',
                                            maxWidth: 200,
                                            minWidth: 100,
                                            dataIndex: 'payment_date',
                                            text: 'Payment Date',
                                            format: 'd M Y'
                                        },
                                        {
                                            xtype: 'templatecolumn',
                                            summaryType: 'sum',
                                            maxWidth: 150,
                                            minWidth: 50,
                                            tpl: [
                                                '${amount}'
                                            ],
                                            defaultWidth: 80,
                                            dataIndex: 'amount',
                                            groupable: true,
                                            text: 'Amount'
                                        }
                                    ],
                                    features: [
                                        {
                                            ftype: 'grouping'
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            ]
        });

        me.callParent(arguments);
    }

});
4

3 回答 3

10

我设法通过使用回调函数使关联查找工作,但发现自己简单地从商店进行查找要容易得多。

第一步

我将代理从 InvoiceStatus 存储移到 InvoiceStatus 模型上,并使 InvoiceStatus 存储自动加载。

第二步

我更改了 Status 列的呈现方法,以从 InvoiceStatus 存储中查找显示名称,如下所示。

renderer: function(value, metaData, record, rowIndex, colIndex, store, view) {
    var store = Ext.data.StoreManager.lookup('InvoiceStatus');
    return store.getById(value).get('name');
},

这被证明是一个更简单的解决方案。

于 2013-04-15T03:27:38.163 回答
3

你的 hasOne 应该是这样的:

hasOne: {
    name:           'status',
    instanceName:   'status',
    associationKey: 'status',
    model:          'MyApp.model.InvoiceStatus',
    foreignKey:     'invoice_status_id',
    getterName:     'getStatus',
    setterName:     'setStatus'
}

ExtJS 4.2.2 的以下补丁将允许您在dataIndex: 'status.name'没有任何额外渲染器的情况下进行设置。网格将显示一切正常,但排序不起作用。

此解决方案不适用于异步(延迟)状态加载。

Ext.view.Table.prototype.renderCell = function(column, record, recordIndex, rowIndex, columnIndex, out) {
    var me = this,
        selModel = me.selModel,
        cellValues = me.cellValues,
        classes = cellValues.classes,
        // fieldValue = record.data[column.dataIndex]; // patched
        fieldValue = null,
        cellTpl = me.cellTpl,
        fullIndex, value, clsInsertPoint;

    // Patch start
    if (column.dataIndex && column.dataIndex.indexOf('.') > 0) {
        var associationParts = column.dataIndex.split('.'),
            v = record;

        for (var i = 0; i < associationParts.length-1; i++) {
            v = v['get' + associationParts[i].charAt(0).toUpperCase() + associationParts[i].slice(1)]();
        }
        fieldValue = v.get(associationParts[associationParts.length-1]);
    }
    else {
        fieldValue = record.data[column.dataIndex];
    }
    // Patch end

    cellValues.record = record;
    cellValues.column = column;
    cellValues.recordIndex = recordIndex;
    cellValues.rowIndex = rowIndex;
    cellValues.columnIndex = columnIndex;
    cellValues.cellIndex = columnIndex;
    cellValues.align = column.align;
    cellValues.tdCls = column.tdCls;
    cellValues.innerCls = column.innerCls;
    cellValues.style = cellValues.tdAttr = "";
    cellValues.unselectableAttr = me.enableTextSelection ? '' : 'unselectable="on"';

    if (column.renderer && column.renderer.call) {
        fullIndex = me.ownerCt.columnManager.getHeaderIndex(column);
        value = column.renderer.call(column.scope || me.ownerCt, fieldValue, cellValues, record, recordIndex, fullIndex, me.dataSource, me);
        if (cellValues.css) {
            // This warning attribute is used by the compat layer
            // TODO: remove when compat layer becomes deprecated
            record.cssWarning = true;
            cellValues.tdCls += ' ' + cellValues.css;
            delete cellValues.css;
        }
    } else {
        value = fieldValue;
    }
    cellValues.value = (value == null || value === '') ? '&#160;' : value;

    // Calculate classes to add to cell
    classes[1] = column.getCellId();

    // On IE8, array[len] = 'foo' is twice as fast as array.push('foo')
    // So keep an insertion point and use assignment to help IE!
    clsInsertPoint = 2;

    if (column.tdCls) {
        classes[clsInsertPoint++] = column.tdCls;
    }
    if (me.markDirty && record.isModified(column.dataIndex)) {
        classes[clsInsertPoint++] = me.dirtyCls;
    }
    if (column.isFirstVisible) {
        classes[clsInsertPoint++] = me.firstCls;
    }
    if (column.isLastVisible) {
        classes[clsInsertPoint++] = me.lastCls;
    }
    if (!me.enableTextSelection) {
        classes[clsInsertPoint++] = me.unselectableCls;
    }
    if (cellValues.tdCls) {
        classes[clsInsertPoint++] = cellValues.tdCls;
    }
    if (selModel && selModel.isCellModel && selModel.isCellSelected(me, recordIndex, columnIndex)) {
        classes[clsInsertPoint++] = (me.selectedCellCls);
    }

    // Chop back array to only what we've set
    classes.length = clsInsertPoint;

    cellValues.tdCls = classes.join(' ');

    cellTpl.applyOut(cellValues, out);

    // Dereference objects since cellValues is a persistent var in the XTemplate's scope chain
        cellValues.column = null;
};
于 2013-10-05T14:19:13.087 回答
3

看起来您需要在子模型上设置belongsTo关联。InvoiceStatus您会认为在一个方向上定义关联会自动在另一个方向上创建关联,但显然情况并非如此,您必须在父级和子级上都定义关联。有关更详细的说明,请参见此处:为什么我的 ExtJS Store Association 不起作用

于 2013-04-15T00:37:50.997 回答