EXT JS 4 use an model association to render a grid display value

extjs, extjs-mvc, extjs4

Solution

I managed to get the association lookup working by using a callback function but found it much easier to simply do the lookup from the store myself.

Step One

I moved the Proxy from the InvoiceStatus store and onto the InvoiceStatus model and made the InvoiceStatus store autoload.

Step Two

I changed the render method of the Status column to lookup the display name from the InvoiceStatus store like so.

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

This proved to be a much simpeler solution.

Problem

Details I have a grid used to display invoice information. The grid is populated using the Invoice store, the Invoice store uses the Invoice model, the Invoice model has a "has one" association with the InvoiceStatus model with a primary key of 'id' and a foren key of 'invoice_status_id'. Problem I'm not sure how to make the display value of the Invoice Grid's 'Status' column use the associated models 'name' inserted of the invoice_status_id. I know I need to create a renderer to do this however I still get a null value. Both the Invoice and InvoiceStatus stors are populating with the correct values. Status Column Render ``` renderer: function(value, metaData, record, rowIndex, colIndex, store, view) { return record.getStatus().get('name'); }, ``` Invoice Store ``` 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)]); } }); ``` InvoiceStatus Store ``` 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)]); } }); ``` Invoice Model ``` 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' } }); ``` InvoiceStatus Model ``` Ext.define('MyApp.model.InvoiceStatus', { extend: 'Ext.data.Model', fields: [ { mapping: 'id', name: 'id', type: 'int' }, { mapping: 'name', name: 'name', type: 'string' } ] }); ``` Invoice Grid ``` 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); } }); ```

Original source

Related problems