Success! Looks like we've fixed this one. According to our records the fix was applied for EXTJS-8251 in 4.2.0.489.
  1. #1
    Sencha User
    Join Date
    Feb 2012
    Posts
    21
    Vote Rating
    2
    alexmipego is on a distinguished road

      0  

    Default Grouping Feature bug/leak

    Grouping Feature bug/leak


    I've a window with a grid using the grouping feature that works fine the first time I open it, but fails with the following error if I close/destroy it and re-open it:

    Code:
    Cannot call method 'getGroupField' of null
    I've come to understand that the problem is the fact that the Grouping feature isn't being properly destroyed, and that behaviour seems to apply to all features and even previous 4.x versions. I've tried to understand the code and I've set many breakpoints on both 4.1.3 and 4.2 but the destroy event (or others related) never seem to be called.

    Anyway, focusing on this particular bug, the new Grouping feature creates a new store (GroupingStore) to be used as a datasource, but the code doesn't handle the view destruction in anyway. I'm unsure about a proper fix for these lifecycle problems but what I did was to override that special store and use a "view.mon" to make sure the view's destruction actually stops the original store's event from propagating all the way down to the "dead" feature.

    Here's my code as a reference:
    Code:
    Ext.override(Ext.grid.feature.GroupStore, {    bindStore: function(store) {
            var me = this;
    
            if(me.store) {
                Ext.destroy(me.storeListeners);
                me.store = null;
            }
            if(store) {
                me.storeListeners = me.groupingFeature.view.mon(store, {
                    bulkremove: me.onBulkRemove,
                    add: me.onAdd,
                    update: me.onUpdate,
                    refresh: me.onRefresh,
                    clear: me.onClear,
                    scope: me,
                    destroyable: true
                });
                me.store = store;
            }
        }
    });

  2. #2
    Sencha - Ext JS Dev Team evant's Avatar
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    16,850
    Vote Rating
    610
    evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute evant has a reputation beyond repute

      0  

    Default


    What you've posted isn't really clear, please post a test case:

    Code:
    Ext.require('*');
    
    Ext.onReady(function() {
        
        var feature = new Ext.grid.feature.Grouping();
        
        new Ext.button.Button({
            renderTo: document.body,
            text: 'Create',
            handler: function(){
                new Ext.window.Window({
                    autoShow: true,
                    layout: 'fit',
                    width: 400,
                    height: 200,
                    items: {
                        features: [feature],
                        xtype: 'gridpanel',
                        store: {
                            groupField: 'group',
                            fields: ['name', 'group'],
                            data: [{
                                group: 'g1',
                                name: 'Foo'
                            }, {
                                group: 'g2',
                                name: 'Bar'
                            }]
                        },
                        columns: [{
                            dataIndex: 'name',
                            text: 'Name'
                        }]
                    }
                });
            }
        });
        
    });
    Evan Trimboli
    Sencha Developer
    Twitter - @evantrimboli
    Don't be afraid of the source code!

  3. #3
    Sencha User
    Join Date
    Feb 2012
    Posts
    21
    Vote Rating
    2
    alexmipego is on a distinguished road

      0  

    Default


    Very well, it's pretty easy actually, just destroy the GridView and then update the original store. Code:
    Code:
    <html>
    	<head>
    		<LINK href="http://cdn.sencha.com/ext/beta/4.2.0.265/resources/css/ext-all.css" rel="stylesheet" type="text/css">
    		<script type="text/javascript" src="http://cdn.sencha.com/ext/beta/4.2.0.265/ext-all-dev.js"></script>
    		<script type="text/javascript">
    			Ext.require('*');
    
    
    			Ext.onReady(function() {
    
    
    				var aCommonStore = new Ext.data.Store({
    					groupField: 'group',
    					fields: ['name', 'group'],
    					data: [{
    						group: 'g1',
    						name: 'Foo'
    					}, {
    						group: 'g2',
    						name: 'Bar'
    					}]
    				});
    
    
    				new Ext.button.Button({
    					renderTo: document.body,
    					text: 'Create',
    					handler: function() {
    						new Ext.window.Window({
    							autoShow: true,
    							layout: 'fit',
    							width: 400,
    							height: 200,
    							items: {
    								features: [{
    									ftype: 'grouping'
    								}],
    								xtype: 'gridpanel',
    								store: aCommonStore,
    								columns: [{
    									dataIndex: 'name',
    									text: 'Name'
    								}]
    							}
    						});
    					}
    				});
    
    
    				new Ext.button.Button({
    					renderTo: document.body,
    					text: 'Trigger a store operation',
    					handler: function() {
    						aCommonStore.add({
    							group: 'g1',
    							name: 'Foo' + (new Date()).getTime()
    						});
    					}
    				});
    			});
    		</script>
    	</head>
    </html>
    With the code above, click the create window and then close it. If you then change the store (aCommonStore) in any way (e.g. click the second button) you'll get an error. In my case, with the latest stable chrome for mac:

    Code:
    A good starting point on that stacktrace to understand my original explanation is the
    Code:
    [COLOR=red !important]Ext.define.onAdd [/COLOR]ext-all-dev.js:157198
    line. If you inspect that code you'll see it lives inside a GroupingStore created the first time you opened the sample's window. The GroupingStore is still listening for the events and eventually it will fail with errors relating to the feature's view missing because it was destroyed.

    The fix I posted can be copy pasted into this test case as well. All it changes is the way the GroupingStore observes the events, with "mon"/managed events when the view is destroyed it stops observing the original store's example. But as I said in the first post, I don't think there's a proper cleanup process for any feature and I believe a proper livecyle (e.g. call feature.destroy) should be implemented.

Thread Participants: 1