1. #1
    Sencha Premium Member
    Join Date
    Oct 2013
    Posts
    39
    Answers
    5
    Vote Rating
    2
    jocatastar is on a distinguished road

      0  

    Default Answered: Prevent listener function expansion on row collapse

    Answered: Prevent listener function expansion on row collapse


    I am using Ext Js 4.2.2 and i developing a grid that includes a row expansion.

    In row expansion i used a listener "itemdblclick". When anyone double click on a row the row will expand and get the values from database and i am showing those values. Upto this perfect.

    If i want to close the expansion of the row , i am again double click on that row and the row expansion collapses well but fires the listener again and one call is going to database to get values.This call to database is not required when collapsing the row expansion on double click.

    Suggest me event or trick to achieve this

  2. Ok, either you try to get the listeners working - you should look up how to listen directly to the events fired by the view - , or you simply do it the dirty way and assign some variable to your record like myexpanded and set it true / false accordingly:

    Code:
    if(!record.myexpanded){
    record.myexpanded = true; expandRow(index, record);
    } else {
    record.myexpanded = false;
    collapseRow(index,record);
    }
    Still it would be nice if you figured out how to do it via listeners. Your code at least theoretically seems to support this.

  3. #2
    Sencha User
    Join Date
    May 2013
    Posts
    20
    Answers
    2
    Vote Rating
    4
    Orcyano is on a distinguished road

      0  

    Default


    did you try event.stopEvent() ?

  4. #3
    Sencha Premium Member
    Join Date
    Oct 2013
    Posts
    39
    Answers
    5
    Vote Rating
    2
    jocatastar is on a distinguished road

      0  

    Default


    If i do that when i want to expand also that will not work right.
    I am doing expansion code itemdblclck listener , if i do your thing then expansion also do not work it seems

  5. #4
    Sencha User
    Join Date
    May 2013
    Posts
    20
    Answers
    2
    Vote Rating
    4
    Orcyano is on a distinguished road

      0  

    Default


    Hmm without some code i'm afraid i can't help you any further than that, as that's what i would normally do.

    Code:
        listeners: {
             itemdblclick: function( el, record, item, index, e, eOpts ){
                 e.stopEvent();
                 // your other code, e.g. expand your row or collapse it, depending on it's current state
             }
        }

  6. #5
    Sencha Premium Member
    Join Date
    Oct 2013
    Posts
    39
    Answers
    5
    Vote Rating
    2
    jocatastar is on a distinguished road

      0  

    Default


    Thanks for the reply

    Here is my code

    listeners : {
    itemdblclick : function(dv, record, item, index, e,
    rowid) {
    expandrow(index, record);
    }
    },

    expandrow is the function which triggers to Database.
    When i hit double click expansion works fine and it is going to database and getting values.

    If i again hit double click the expansion is closed but again database call is happening. This should not happen. Only it should collapse the row expansion , but call to the database should not happen. This is what i am looking for

  7. #6
    Sencha User
    Join Date
    May 2013
    Posts
    20
    Answers
    2
    Vote Rating
    4
    Orcyano is on a distinguished road

      0  

    Default


    I've just looked it up in the sencha docs, because i was wondering that there ain't a direct way to detect row expansion / collapsing as with all other components that support such actions, and i found those:
    - expandbody( rowNode, record, expandRow, eOpts )
    - collapsebody( rowNode, record, expandRow, eOpts )

    The events are triggered when expanded/collapsed. For your purposes it should be enough to use the expandbody event.
    According to the docs you simply supply these listeners within the grids listeners configuration, at least thats what i understand when i read it:
    "Fired through the grid's View."

    Have a go and test it

    EDIT:
    If you wanna keep your code and just edit it to not execute a database query, then supply a variable that identifies the current status of your row (expanded/collapsed) and act accordingly. Maybe there is even a pre-defined way to detect if your row is already expanded. You should look up your rows properties with Firebug or Chrome-Dev-Tools.

  8. #7
    Sencha Premium Member
    Join Date
    Oct 2013
    Posts
    39
    Answers
    5
    Vote Rating
    2
    jocatastar is on a distinguished road

      0  

    Default


    No it will not work because i am using customrowexpander. Here is the code for customrowexpander.
    That does not have functions like expandbody,collapsebody
    Code:
    Ext
    .define(
            'Ext.ux.CustomRowExpander',
            {
                extend : 'Ext.AbstractPlugin',
                lockableScope : 'normal',
                alias : 'plugin.customrowexpander',
    
                rowBodyTpl : null,
    
                /**
                 * @cfg {Boolean} expandOnEnter <tt>true</tt> to toggle
                 *      selected row(s) between expanded/collapsed when the
                 *      enter key is pressed (defaults to <tt>true</tt>).
                 */
                expandOnEnter : true,
    
                /**
                 * @cfg {Boolean} expandOnDblClick <tt>true</tt> to toggle
                 *      a row between expanded/collapsed when double clicked
                 *      (defaults to <tt>true</tt>).
                 */
                expandOnDblClick : true,
    
                /**
                 * @cfg {Boolean} selectRowOnExpand <tt>true</tt> to
                 *      select a row when clicking on the expander icon
                 *      (defaults to <tt>false</tt>).
                 */
                selectRowOnExpand : false,
    
                rowBodyTrSelector : '.x-grid-rowbody-tr',
                rowBodyHiddenCls : 'x-grid-row-body-hidden',
                rowCollapsedCls : 'x-grid-row-collapsed',
    
                addCollapsedCls : {
                    before : function(values, out) {
                        var me = this.rowExpander;
                        if (!me.recordsExpanded[values.record.internalId]) {
                            values.itemClasses.push(me.rowCollapsedCls);
                        }
                    },
                    priority : 500
                },
    
                /**
                 * @event expandbody **Fired through the grid's View**
                 * @param {HTMLElement}
                 *            rowNode The &lt;tr> element which owns the
                 *            expanded row.
                 * @param {Ext.data.Model}
                 *            record The record providing the data.
                 * @param {HTMLElement}
                 *            expandRow The &lt;tr> element containing the
                 *            expanded data.
                 */
                /**
                 * @event collapsebody **Fired through the grid's View.**
                 * @param {HTMLElement}
                 *            rowNode The &lt;tr> element which owns the
                 *            expanded row.
                 * @param {Ext.data.Model}
                 *            record The record providing the data.
                 * @param {HTMLElement}
                 *            expandRow The &lt;tr> element containing the
                 *            expanded data.
                 */
    
                setCmp : function(grid) {
                    var me = this, rowBodyTpl, features;
    
                    me.callParent(arguments);
    
                    me.recordsExpanded = {};
                    if (!me.rowBodyTpl) {
                        Ext.Error
                                .raise("The 'rowBodyTpl' config is required and is not defined.");
                    }
    
                    me.rowBodyTpl = Ext.XTemplate.getTpl(me, 'rowBodyTpl');
                    rowBodyTpl = this.rowBodyTpl;
                    features = [
                            {
                                ftype : 'rowbody',
                                lockableScope : 'normal',
                                recordsExpanded : me.recordsExpanded,
                                rowBodyHiddenCls : me.rowBodyHiddenCls,
                                rowCollapsedCls : me.rowCollapsedCls,
                                setupRowData : me.getRowBodyFeatureData,
                                setup : me.setup,
                                getRowBodyContents : function(record) {
                                    return rowBodyTpl.applyTemplate(record
                                            .getData());
                                }
                            }, {
                                ftype : 'rowwrap',
                                lockableScope : 'normal'
                            } ];
    
                    if (grid.features) {
                        grid.features = Ext.Array.push(features,
                                grid.features);
                    } else {
                        grid.features = features;
                    }
                    // NOTE: features have to be added before init (before
                    // Table.initComponent)
                },
    
                init : function(grid) {
                    var me = this, reconfigurable = grid, view, lockedView;
    
                    me.callParent(arguments);
                    me.grid = grid;
                    view = me.view = grid.getView();
                    // Columns have to be added in init (after columns has
                    // been used to create the headerCt).
                    // Otherwise, shared column configs get corrupted, e.g.,
                    // if put in the prototype.
                    // me.addExpander();
    
                    // Bind to view for key and mouse events
                    // Add row processor which adds collapsed class
                    me.bindView(view);
                    view.addRowTpl(me.addCollapsedCls).rowExpander = me;
    
                    // If the owning grid is lockable, then disable row
                    // height syncing - we do it here.
                    // Also ensure the collapsed class is applied to the
                    // locked side by adding a row processor.
                    if (grid.ownerLockable) {
                        // If our client grid is the normal side of a
                        // lockable grid, we listen to its lockable owner's
                        // beforereconfigure
                        reconfigurable = grid.ownerLockable;
                        reconfigurable.syncRowHeight = false;
                        lockedView = reconfigurable.lockedGrid.getView();
    
                        // Bind to locked view for key and mouse events
                        // Add row processor which adds collapsed class
                        me.bindView(lockedView);
                        lockedView.addRowTpl(me.addCollapsedCls).rowExpander = me;
    
                        // Refresh row heights of expended rows on the
                        // locked (non body containing) side upon lock &
                        // unlock.
                        // The locked side's expanded rows will collapse
                        // back because there's no body there
                        reconfigurable.mon(reconfigurable,
                                'columnschanged', me.refreshRowHeights, me);
                        reconfigurable.mon(reconfigurable.store,
                                'datachanged', me.refreshRowHeights, me);
                    }
                    reconfigurable.on('beforereconfigure',
                            me.beforeReconfigure, me);
    
                    if (grid.ownerLockable && !grid.rowLines) {
                        // grids without row lines can gain a border when
                        // focused. When they do, the
                        // stylesheet adjusts the padding of the cells so
                        // that the height of the row
                        // does not change. It is necessary to refresh the
                        // row heights for lockable
                        // grids on focus to keep the height of the expander
                        // cells in sync.
                        view.on('rowfocus', me.refreshRowHeights, me);
                    }
                },
    
                beforeReconfigure : function(grid, store, columns,
                        oldStore, oldColumns) {
                    var expander = this.getHeaderConfig();
                    expander.locked = true;
                    columns.unshift(expander);
                },
    
                /**
                 * @private Inject the expander column into the correct
                 *          grid.
                 * 
                 * If we are expanding the normal side of a lockable grid,
                 * poke the column into the locked side
                 */
                addExpander : function() {
                    var me = this, expanderGrid = me.grid, expanderHeader = me
                            .getHeaderConfig();
    
                    // If this is the normal side of a lockable grid, find
                    // the other side.
                    if (expanderGrid.ownerLockable) {
                        expanderGrid = expanderGrid.ownerLockable.lockedGrid;
                        expanderGrid.width += expanderHeader.width;
                    }
                    expanderGrid.headerCt.insert(0, expanderHeader);
                },
    
                getRowBodyFeatureData : function(record, idx, rowValues) {
                    var me = this;
                    me.self.prototype.setupRowData.apply(me, arguments);
    
                    rowValues.rowBody = me.getRowBodyContents(record);
                    rowValues.rowBodyCls = me.recordsExpanded[record.internalId] ? ''
                            : me.rowBodyHiddenCls;
                },
    
                setup : function(rows, rowValues) {
                    var me = this;
                    me.self.prototype.setup.apply(me, arguments);
                    // If we are lockable, the expander column is moved into
                    // the locked side, so we don't have to span it
                    if (!me.grid.ownerLockable) {
                        rowValues.rowBodyColspan -= 1;
                    }
                },
    
                bindView : function(view) {
                    if (this.expandOnEnter) {
                        view.on('itemkeydown', this.onKeyDown, this);
                    }
                    if (this.expandOnDblClick) {
                        view.on('itemdblclick', this.onDblClick, this);
                    }
                },
    
                onKeyDown : function(view, record, row, rowIdx, e) {
                    if (e.getKey() == e.ENTER) {
                        var ds = view.store, sels = view
                                .getSelectionModel().getSelection(), ln = sels.length, i = 0;
    
                        for (; i < ln; i++) {
                            rowIdx = ds.indexOf(sels[i]);
                            this.toggleRow(rowIdx, sels[i]);
                        }
                    }
                },
    
                onDblClick : function(view, record, row, rowIdx, e) {
                    this.toggleRow(rowIdx, record);
                },
    
                toggleRow : function(rowIdx, record) {
                    var me = this, view = me.view, rowNode = view
                            .getNode(rowIdx), row = Ext.fly(rowNode,
                            '_rowExpander'), nextBd = row.down(
                            me.rowBodyTrSelector, true), isCollapsed = row
                            .hasCls(me.rowCollapsedCls), addOrRemoveCls = isCollapsed ? 'removeCls'
                            : 'addCls', ownerLock, rowHeight, fireView;
    
                    // Suspend layouts because of possible TWO views having
                    // their height change
                    Ext.suspendLayouts();
                    row[addOrRemoveCls](me.rowCollapsedCls);
                    Ext.fly(nextBd)[addOrRemoveCls](me.rowBodyHiddenCls);
                    me.recordsExpanded[record.internalId] = isCollapsed;
                    view.refreshSize();
    
                    // Sync the height and class of the row on the locked
                    // side
                    if (me.grid.ownerLockable) {
                        ownerLock = me.grid.ownerLockable;
                        fireView = ownerLock.getView();
                        view = ownerLock.lockedGrid.view;
                        rowHeight = row.getHeight();
                        row = Ext.fly(view.getNode(rowIdx), '_rowExpander');
                        row.setHeight(rowHeight);
                        row[addOrRemoveCls](me.rowCollapsedCls);
                        view.refreshSize();
                    } else {
                        fireView = view;
                    }
                    fireView.fireEvent(isCollapsed ? 'expandbody'
                            : 'collapsebody', row.dom, record, nextBd);
                    // Coalesce laying out due to view size changes
                    Ext.resumeLayouts(true);
                },
    
                // refreshRowHeights often gets called in the middle of some
                // complex processing.
                // For example, it's called on the store's datachanged
                // event, but it must execute
                // *after* other objects interested in datachanged have done
                // their job.
                // Or it's called on column lock/unlock, but that could be
                // just the start of a cross-container
                // drag/drop of column headers which then moves the column
                // into its final place.
                // So this throws execution forwards until the idle event.
                refreshRowHeights : function() {
                    Ext.globalEvents.on({
                        idle : this.doRefreshRowHeights,
                        scope : this,
                        single : true
                    });
                },
    
                doRefreshRowHeights : function() {
                    var me = this, recordsExpanded = me.recordsExpanded, key, record, lockedView = me.grid.ownerLockable.lockedGrid.view, normalView = me.grid.ownerLockable.normalGrid.view, normalRow, lockedRow, lockedHeight, normalHeight;
    
                    for (key in recordsExpanded) {
                        if (recordsExpanded.hasOwnProperty(key)) {
                            record = this.view.store.data.get(key);
                            lockedRow = lockedView.getNode(record, false);
                            normalRow = normalView.getNode(record, false);
                            lockedRow.style.height = normalRow.style.height = '';
                            lockedHeight = lockedRow.offsetHeight;
                            normalHeight = normalRow.offsetHeight;
                            if (normalHeight > lockedHeight) {
                                lockedRow.style.height = normalHeight
                                        + 'px';
                            } else if (lockedHeight > normalHeight) {
                                normalRow.style.height = lockedHeight
                                        + 'px';
                            }
                        }
                    }
                },
    
                getHeaderConfig : function() {
                    var me = this;
    
                    return {
                        width : 24,
                        lockable : false,
                        sortable : false,
                        resizable : false,
                        draggable : false,
                        hideable : false,
                        menuDisabled : true,
                        tdCls : Ext.baseCSSPrefix + 'grid-cell-special',
                        innerCls : Ext.baseCSSPrefix
                                + 'grid-cell-inner-row-expander',
                        renderer : function(value, metadata) {
                            // Only has to span 2 rows if it is not in a
                            // lockable grid.
                            if (!me.grid.ownerLockable) {
                                metadata.tdAttr += ' rowspan="2"';
                            }
                            return '<div class="' + Ext.baseCSSPrefix
                                    + 'grid-row-expander"></div>';
                        },
                        processEvent : function(type, view, cell, rowIndex,
                                cellIndex, e, record) {
                            if (type == "mousedown"
                                    && e.getTarget('.x-grid-row-expander')) {
                                me.toggleRow(rowIndex, record);
                                return me.selectRowOnExpand;
                            }
                        }
                    };
                }
            });

  9. #8
    Sencha User
    Join Date
    May 2013
    Posts
    20
    Answers
    2
    Vote Rating
    4
    Orcyano is on a distinguished road

      0  

    Default


    Next time please at least put it into code brackets ....

    Ok, but to get back to the problem, your Custom RowExpander also got those events, you can find the fire statement within the toggleRow function - which is executed on double click:
    Code:
                    fireView.fireEvent(isCollapsed ? 'expandbody' : 'collapsebody', row.dom, record, nextBd); // Coalesce laying out due to view size changes 
                    Ext.resumeLayouts(true);
    You said that it would not work, but you actually never tried?
    Then i'd suggest you just try it out.
    Any error output on the console? Or just nothing happening?

  10. #9
    Sencha Premium Member
    Join Date
    Oct 2013
    Posts
    39
    Answers
    5
    Vote Rating
    2
    jocatastar is on a distinguished road

      0  

    Default


    Thanks for the reply, i have tried using expandbody but nothing happens, no error in the console. Even i put alert inside listeners, it is not going into listener if i use expand body. Here is the one which i had tried


    Code:
    Code:
    listeners : {
            expandbody: function(dv, record, item, index, e,
                    rowid) {
                expandCaseRow(index, record);
            }
        }

  11. #10
    Sencha User
    Join Date
    May 2013
    Posts
    20
    Answers
    2
    Vote Rating
    4
    Orcyano is on a distinguished road

      0  

    Default


    what is the output on the console if you do a
    console.log(fireView);
    right before the event is triggered within the toggleRow function?

Thread Participants: 2