Tutorial ExtJS 4: Grid Mestre-Detalhe usando plugin RowExpander e Model Associations

31/07/2012 | By | 14 Comments

No post de hoje vamos aprender como implementar um grid em ExtJS 4 usando Model Associations, e por isso, o grid sera do tipo Mestre-Detalhe, e para isso vamos usar também um plugin chamado RowExpander (com algumas modificações para atender a esse requisito).

Este é um dos tutoriais mais pedidos que recebo por email. Vamos então implementá-lo. No post de hoje vou mostrar a maneira mais simples possível de fazer isso. Na verdade vou usar uma solução que já existe e apenas replicar aqui no blog.

Requisitos:

Passos:

  1. Declarar os Models com Associações
  2. Criar dados de teste – json
  3. Criar os Grids

1 – Models com Associações

Ext.define('Company', {
    extend     : 'Ext.data.Model',
    idProperty : 'companyId',
    fields     : [
        'company',
        'price',
        'change',
        'pctChange',
        { name : 'lastChange', type : 'date', dateFormat : 'n/j g:ia' }
    ],

    proxy    : {
        type   : 'ajax',
        url    : 'hasMany.json',
        reader : {
            type : 'json',
            root : 'data'
        }
    },

    hasMany    : {
        model : 'History',
        name  : 'history'
    }
});

Ext.define('History', {
    extend : 'Ext.data.Model',
    fields : [
        { name : 'date', type : 'date', dateFormat : 'n/j g:ia' },
        'text',
        'companyId'
    ],

    proxy : {
        type   : 'ajax',
        url    : 'belongsTo.json',
        reader : {
            type : 'json',
            root : 'data'
        }
    },

    belongsTo : {
        model      : 'Company',
        name       : 'companies',
        foreignKey : 'companyId'
    },

    hasOne : {
        model      : 'Company',
        name       : 'companies',
        foreignKey : 'companyId',
        getterName : 'getCompanyOne'
    }
});

2 – Dados de Teste – json

2.1 – HasMany – json

{
    "data": [
        {
            "companyId": 1,
            "company": "3m Co",
            "price": 71.72,
            "change": -0.02,
            "pctChange": -0.03,
            "lastChange": "9/1 12:00am",
            "history" : [
                { "date" : "9/1 12:00am", "text" : "Test" },
                { "date" : "8/1 12:00am", "text" : "Initial" }
            ]
        },
        {
            "companyId": 2,
            "company": "Alcoa Inc",
            "price": 29.01,
            "change": 0.42,
            "pctChange": 1.47,
            "lastChange": "9/1 12:00am",
            "history" : [
                { "date" : "9/1 12:00am", "text" : "Test" },
                { "date" : "8/1 12:00am", "text" : "Initial" }
            ]
        },
        {
            "companyId": 3,
            "company": "Altria Group Inc",
            "price": 83.81,
            "change": 0.28,
            "pctChange": 0.34,
            "lastChange": "9/1 12:00am",
            "history" : [
                { "date" : "9/1 12:00am", "text" : "Test" },
                { "date" : "8/1 12:00am", "text" : "Initial" }
            ]
        }
    ]
}

2.2 – BelongsTo – json

{
    "data": [
        {
            "date": "9/1 12:00am",
            "text": "Test",
            "companyId": 1
        },
        {
            "date": "8/1 12:00am",
            "text": "Initial",
            "companyId": 2
        }
    ]
}

3 – Criação dos Grids

3.1 – HasMany – com Grid

extjs4 master detail 01 Tutorial ExtJS 4: Grid Mestre Detalhe usando plugin RowExpander e Model Associations

Ext.create('Ext.grid.Panel',{
    store    : Ext.create('Ext.data.Store',{
        model    : 'Company',
        autoLoad : true,
        proxy    : {
            type   : 'ajax',
            url    : 'hasMany.json',
            reader : {
                type : 'json',
                root : 'data'
            }
        }
    }),
    renderTo : 'hasManyGrid',
    width    : 600,
    height   : 300,
    columns  : [
        { text : 'Company',      dataIndex : 'company',        flex : 1                                     },
        { text : 'Price',        dataIndex : 'price',      renderer : Ext.util.Format.usMoney               },
        { text : 'Change',       dataIndex : 'change'                                                       },
        { text : '% Change',     dataIndex : 'pctChange'                                                    },
        { text : 'Last Updated', dataIndex : 'lastChange', renderer : Ext.util.Format.dateRenderer('m/d/Y') }
    ],
    plugins : [
        {
            ptype      : 'associationrowexpander',
            getterName : 'history',
            gridConfig : {
                height  : 100,
                title   : 'History',
                columns : [
                    {
                        header    : 'Text',
                        dataIndex : 'text',
                        flex      : 1
                    },
                    {
                        header    : 'Date',
                        dataIndex : 'date',
                        width     : 200,
                        renderer  : Ext.util.Format.dateRenderer('n/j g:ia')
                    }
                ]
            }
        }
    ]
});

3.2 – HasMany – com View

extjs4 master detail 02 Tutorial ExtJS 4: Grid Mestre Detalhe usando plugin RowExpander e Model Associations

Ext.create('Ext.grid.Panel',{
    store    : Ext.create('Ext.data.Store',{
        model    : 'Company',
        autoLoad : true,
        proxy    : {
            type   : 'ajax',
            url    : 'hasMany.json',
            reader : {
                type : 'json',
                root : 'data'
            }
        }
    }),
    renderTo : 'hasManyView',
    width    : 600,
    height   : 300,
    columns  : [
        { text : 'Company',      dataIndex : 'company',        flex : 1                                     },
        { text : 'Price',        dataIndex : 'price',      renderer : Ext.util.Format.usMoney               },
        { text : 'Change',       dataIndex : 'change'                                                       },
        { text : '% Change',     dataIndex : 'pctChange'                                                    },
        { text : 'Last Updated', dataIndex : 'lastChange', renderer : Ext.util.Format.dateRenderer('m/d/Y') }
    ],
    plugins : [
        {
            ptype      : 'associationrowexpander',
            getterName : 'history',
            viewConfig : {
                itemSelector : 'div.history-text',
                emptyText    : 'There is no history',
                tpl          : new Ext.XTemplate(
                    '<div><b>History</b></div>',
                    '<tpl for=".">',
                        '<div class="history-text">{text} ({date:date("n/j g:ia")})</div>',
                    '</tpl>'
                )
            }
        }
    ]
});

3.3 – BelongsTo – com XTemplate

extjs4 master detail 03 Tutorial ExtJS 4: Grid Mestre Detalhe usando plugin RowExpander e Model Associations

Ext.create('Ext.grid.Panel',{
    store    : Ext.create('Ext.data.Store',{
        model    : 'History',
        autoLoad : true
    }),
    renderTo : 'belongsTo',
    width    : 600,
    height   : 300,
    columns  : [
        { text : 'Text', dataIndex : 'text',     flex : 1                                     },
        { text : 'Date', dataIndex : 'date', renderer : Ext.util.Format.dateRenderer('m/d/Y') }
    ],
    plugins : [
        {
            ptype      : 'associationrowexpander',
            type       : 'belongsTo',
            getterName : 'getCompany',
            rowBodyTpl : new Ext.XTemplate(
                             '<div><b>Company Details:</b></div>',
                             '<div>{company} - {[this.colorVal(values.price, true)]}</div>',
                             '<div>{lastChange:date("n/j g:ia")}</div>',
                             '<div>{[this.colorVal(values.change, true)]} {[this.colorVal(values.pctChange, false)]}</div>',
                             {
                                 colorVal : function(value, money) {
                                     var color = value === 0 ? '000' : (value > 0 ? '093' : 'F00');

                                     if (money) {
                                         value = Ext.util.Format.usMoney(value);
                                     } else {
                                         value += '%';
                                     }

                                     return '<span style="color: #' + color + ';">' + value + '</span>';
                                 }
                             }
                         )
        }
    ]
});

3.4 – HasOne – com XTemplate

extjs4 master detail 04 Tutorial ExtJS 4: Grid Mestre Detalhe usando plugin RowExpander e Model Associations

Ext.create('Ext.grid.Panel',{
    store    : Ext.create('Ext.data.Store',{
        model    : 'History',
        autoLoad : true
    }),
    renderTo : 'hasOne',
    width    : 600,
    height   : 300,
    columns  : [
        { text : 'Text', dataIndex : 'text',     flex : 1                                     },
        { text : 'Date', dataIndex : 'date', renderer : Ext.util.Format.dateRenderer('m/d/Y') }
    ],
    plugins : [
        {
            ptype      : 'associationrowexpander',
            type       : 'hasOne',
            getterName : 'getCompanyOne',
            rowBodyTpl : new Ext.XTemplate(
                             '<div><b>Company Details:</b></div>',
                             '<div>{company} - {[this.colorVal(values.price, true)]}</div>',
                             '<div>{lastChange:date("n/j g:ia")}</div>',
                             '<div>{[this.colorVal(values.change, true)]} {[this.colorVal(values.pctChange, false)]}</div>',
                             {
                                 colorVal : function(value, money) {
                                     var color = value === 0 ? '000' : (value > 0 ? '093' : 'F00');

                                     if (money) {
                                         value = Ext.util.Format.usMoney(value);
                                     } else {
                                         value += '%';
                                     }

                                     return '<span style="color: #' + color + ';">' + value + '</span>';
                                 }
                             }
                         )
        }
    ]
});

Download

Demo: http://loiane.com.br/extjs/extjs4-grid-master-detail

Código Fontehttps://github.com/mitchellsimoens/Ux.grid.plugin.AssociationRowExpander

Até a próxima! icon smile Tutorial ExtJS 4: Grid Mestre Detalhe usando plugin RowExpander e Model Associations

Filed in: Ext JS 4 | Tags: , , , ,

Comments (14)

  1. wagner

    Loiane Parabéns realmente muito bom seu post como todos os outros . muito bacana vc compartilhar seu conhecimento ….

  2. wagner

    Ola´loiane o link do demo ta quebrado abrços….

  3. Obrigado pelo post, brilhante!

  4. Nico

    do you have a sample how this
    can be used in a MVC app

  5. Bruno Leite

    Qual a diferença entre belongsTo para o hasOne?

  6. Bonfim

    Loiane, gostei muito do seu post.
    Eu fiz algumas alterações deixando somente o tipo Has Many.
    Porém esta gerando um erro.
    Você pode por favor da uma olhada no post e verificar onde devo ter errado? http://www.extjs.com.br/forum/index.php?topic=7161.0.
    Fico grato pela sua atenção.
    Abs.
    Bonfim

  7. Bonfim

    Loiane,
    Obrigado pelo retorno.Vou seguir as suas orientações.
    Dei uma olhada na internet não encontrei nenhum exemplo prático com 2 grids conforme sua sugestão.Encontrei um tutorial parecido que usa o Couchdb.Se tive alguma outra dica eu agradeço.
    Bonfim

  8. Do you have an exampe with code with date field going in and out from the database?

Leave a Reply

Trackback URL | RSS Feed for This Entry