Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

});
like image 458
Levi Putna Avatar asked Apr 15 '13 00:04

Levi Putna


2 Answers

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.

like image 89
Levi Putna Avatar answered Nov 15 '22 11:11

Levi Putna


It looks like you need to set the belongsTo association on the InvoiceStatus child model. You would think that defining the association in one direction would automatically create the association in the other direction, but apparently that's not the case and you must define the association on both parent and children. See here for a more detailed explanation: Why isn't my ExtJS Store Association Working

like image 3
James Avatar answered Nov 15 '22 12:11

James