1. #1
    Sencha Premium Member
    Join Date
    Nov 2012
    Location
    Waterford, Ireland
    Posts
    2
    Vote Rating
    1
    davidffrench is on a distinguished road

      1  

    Default Ext.ux.RowExpanderWithComponents

    I hope this will be of use to somebody and any issues or improvements found will be gladly accepted.

    Github: https://github.com/davidffrench/Ext.ux.RowExpanderWithComponents
    Demo: https://fiddle.sencha.com/#fiddle/pum
    Code: At bottom of post

    Ext.ux.RowExpanderWithComponents
    Allows the use of ExtJS components inside a row expander


    How to use it:
    Include it as a normal grid plugin. Define a row body template or use the getRowComponent or addToRowComponent functions to add components.
    Code:
    plugins: [{
        ptype: 'rowexpanderwithcomponents',
        rowBodyCompTemplate: {
            xtype: 'container',
            html: '{{company}}',
            items: [{
                xtype: 'label',
                text: '{{price}}'
            }, {
                xtype: 'container',
                html: '{{change}}',
                items: [{
                    xtype: 'button',
                    text: '{{industry}}',
                    itemId: 'davidTest'
                }]
            }]
        }
    }]


    Records must have an id to use the rowExpanderWithComponents plugin.
    Use
    http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.data.Model-cfg-idProperty
    or
    http://docs.sencha.com/extjs/4.2.2/#...odel-cfg-idgen


    Includes a rowBodyCompTemplate property
    Template ExtJS components for each row. {{modelFieldName}} is the dynamic value which will be taken from the model.
    Methods do not work. please use the getRowComponent or addToRowComponent helper functions to achieve this

    Code:
    Code:
    /**
     * RowExpanderWithComponents plugin
     */
    Ext.define('Ext.ux.RowExpanderWithComponents', {
        extend : 'Ext.grid.plugin.RowExpander',
        alias: 'plugin.rowexpanderwithcomponents',
    
    
        /**
         * @cfg {XTemplate} rowBodyTpl
         * This needs to default to the below for ExtJS components to render to the correct row
         * (defaults to <tt><div id="display-row-{id}"> </div></tt>).
         */
        rowBodyTpl : new Ext.XTemplate(
            '<div id="display-row-{id}"> </div>'
        ),
    
    
        /**
         * @cfg {Object} rowBodyCompTemplate
         * Template ExtJS components for each row. {{modelFieldName}} is the dynamic value which will be taken from the model
         * Methods do not work. please use the getRowComponent or addToRowComponent helper functions to achieve this
         * Sample below
         * rowBodyCompTemplate: {
                xtype: 'container',
                html: '{{company}}',
                items: [{
                    xtype: 'button',
                    text: '{{price}}'
                }, {
                    xtype: 'container',
                    html: '{{change}}',
                    items: [{
                        xtype: 'button',
                        text: '{{industry}}'
                    }]
                }]
            }
         * (defaults to <tt>null</tt>).
         */
        rowBodyCompTemplate: null,
    
    
        /**
         * @cfg {Boolean} expandOnClick
         * <tt>true</tt> to toggle a row between expanded/collapsed when single clicked
         * (defaults to <tt>true</tt>).
         */
        expandOnClick: true,
    
    
        /**
         * @cfg {Boolean} hideExpandColumn
         * <tt>true</tt> to hide the column that contains the expand/collapse icons
         * (defaults to <tt>true</tt>).
         */
        hideExpandColumn: true,
    
    
        /**
         * @cfg {Boolean} enableTextSelection
         * <tt>true</tt> to enable text selection within the grid
         * (defaults to <tt>true</tt>).
         */
        enableTextSelection: true,
    
    
        init : function(grid){
            var me = this,
                view;
    
    
            me.callParent(arguments);
    
    
            //get the grids view
            view = me.view = grid.getView();
    
    
            //this css does not highlight the row expander body
            grid.addCls('rowexpanderwithcomponents');
    
    
            //set the rowexpander column to hidden if hideExpandColumn config is true
            if(me.hideExpandColumn){
                grid.headerCt.query('gridcolumn')[0].hidden = true;
            }            
            //enable text selection if the config is true 
            if(me.enableTextSelection){
                view.enableTextSelection = true;
            }
    
    
            view.on('expandbody', function(rowNode, record, expandRow, eOpts){
                var recId = record.getId();
                if(!recId){
                    Ext.Error.raise('Error: Records must have an id to use the rowExpanderWithComponents plugin. Use http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.data.Model-cfg-idProperty or http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.data.Model-cfg-idgen');
                }
    
    
                //if the parent comp is rendered already, return
                var cont = this.getRowComponent(recId);
                if(cont){
                    return;
                }
    
    
                var row = 'display-row-' + recId,
                    clonedRowTemplate = JSON.parse(JSON.stringify(me.rowBodyCompTemplate));
                //parent comp that is rendered to the row. All subsequent components that wil be in the row expander will be children of this
                var parentCont = Ext.create(Ext.container.Container,{
                    height: '100%',
                    width: '100%',
                    itemId: grid.getId() + '-parentRowExpCont-' + recId,
                    items:[
                        me.replaceObjValues(clonedRowTemplate, record)
                    ]
                });
                //render the ExtJS component to the div
                parentCont.render(row);
    
    
                //Stop all events in the row body from bubbling up
                var rowEl = parentCont.getEl().parent('.x-grid-rowbody');
                rowEl.swallowEvent(['mouseenter', 'click', 'mouseover', 'mousedown', 'dblclick', 'cellclick', 'itemmouseenter', 'itemmouseleave', 'onRowFocus', 'mouseleave']);
            });
            //assign the helper functions to the gridview and grid
            view.getRowComponent = me.getRowComponent;
            grid.getRowComponent = me.getRowComponent;
    
    
            grid.addToRowComponent = me.addToRowComponent;
            grid.addToRowComponent = me.addToRowComponent;
        },
        
        /**
         * Gets the parent ExtJS container in the rowexpander body from the rows record id 
         * @param {integer} recId The row record id  
         * @return {Ext.container.Container} the parent ExtJS container in the rowexpander body
         */
        getRowComponent: function(recId){
            return Ext.ComponentQuery.query('#' + this.up('grid').getId() + '-parentRowExpCont-' + recId)[0];
        },
    
    
        /**
         * Removes all ExtJS items from the parent row component
         * @param {integer} recId The row record id  
         */
        removeAllFromRowComponent: function(recId){
            var rowCont = this.getRowComponent(recId);
    
    
            rowCont.removeAll();
        },
    
    
        /**
         * Adds items to the parent ExtJS container in the rowexpander body
         * @param {integer} recId The row record id  
         * @param {Array} items ExtJS components
         */
        addToRowComponent: function(recId, items){
            var rowCont = this.getRowComponent(recId);
    
    
            rowCont.add(items);
        },
    
    
        /**
         * @private
         * allow single click to expand grid
         */
        bindView: function(view) {
            if (this.expandOnClick) {
                view.on('itemclick', this.onItemClick, this);
            }
            this.callParent(arguments);
        },
        /**
         * @private
         * allow single click to expand grid
         */
        onItemClick: function(view, record, row, rowIdx, e) {
            this.toggleRow(rowIdx, record);
        },
    
    
        /**
         * @private
         * Converts all string values with {{}} to record.get()
         * Example: '{{test}}' converts to record.get('test')
         */
        replaceObjValues: function( obj, record ){
            for( var all in obj )
            {
                if( typeof obj[all] === "string" && obj[all].match(/{{(.*)}}/) ){
                    obj[all] = record.get(obj[all].match(/{{(.*)}}/)[1]);
                }
                if( typeof obj[all] === "object" && obj[all]!== null ){
                    this.replaceObjValues( obj[all], record );
                }
            }
            return obj;
        }
    });
    CSS for the plugin
    Code:
    .rowexpanderwithcomponents .x-grid-row-focused .x-grid-data-row {
      background-color: #e2eff8;
    }
    .rowexpanderwithcomponents .x-grid-row-over .x-grid-data-row {
      background-color: #e2eff8;
    }
    .rowexpanderwithcomponents .x-grid-row-selected .x-grid-data-row {
      background-color: #c1ddf1;
    }
    
    
    .rowexpanderwithcomponents .x-grid-row-focused .x-grid-td {
      background-color: transparent;
    }
    .rowexpanderwithcomponents .x-grid-row-over .x-grid-td {
      background-color: transparent;
    }
    .rowexpanderwithcomponents .x-grid-row-selected .x-grid-td {
      background-color: transparent;
    }

  2. #2
    Sencha - Support Team
    Join Date
    Feb 2013
    Location
    California
    Posts
    8,501
    Vote Rating
    227
    Gary Schlosberg has much to be proud of Gary Schlosberg has much to be proud of Gary Schlosberg has much to be proud of Gary Schlosberg has much to be proud of Gary Schlosberg has much to be proud of Gary Schlosberg has much to be proud of Gary Schlosberg has much to be proud of Gary Schlosberg has much to be proud of Gary Schlosberg has much to be proud of

      0  

    Default

    Nice! Do you have a demo? Thanks for sharing your work with the community!


    Join me at SenchaCon 2016!

  3. #3
    Sencha Premium Member
    Join Date
    Nov 2012
    Location
    Waterford, Ireland
    Posts
    2
    Vote Rating
    1
    davidffrench is on a distinguished road

      0  

    Default

    Hi Gary,

    I have put together a basic demo located here:
    https://fiddle.sencha.com/#fiddle/pum

    I have edited my original post with the demo link also.

    David

Thread Participants: 1