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'.
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);
}
});
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.
I moved the Proxy from the InvoiceStatus store and onto the InvoiceStatus model and made the InvoiceStatus store autoload.
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.