PDA

View Full Version : How do I remove listeners once a component is removed?



tm8747a
15 Aug 2013, 12:00 PM
I have a couple components that are related to each other. Basically, I have a panel with a vbox layout onto which rows can be added dynamically clicking on a button in the tbar (call it the RowContainer). Then each row is another panel (RowPanel) that can be removed as long as there's more than one row. So if there's only one row, the button to remove the row is disabled. The way I've implemented it is that I added 'rowadd' and 'rowdelete' events on the RowContainer that fire when rows are added or deleted. Then, each time I add a row, all rows receive an event and can make sure the 'Remove Row' button is visible, since it means there's more than one row. While the Add Row button is in the RowContainer, the Remove Row is inside the RowPanel, so what I do is I have a removeRow function within the RowContainer that basically makes the component remove itself, and then my RowContainer listens to the 'remove' event and just fires its 'rowdelete' event that all other rows listen to. If there's only one row left, the 'Remove Row' button gets disabled.

My problem right now is that when my RowPanel is removed, it disappears on the screen, but the 'rowadd' and 'rowdelete' event they subscribed to from the RowContainer keep firing. I've tried using the un() function to remove those, I've tried using managed listeners (can't even get those to fire, it's weird), nothing seems to work. I must be missing something. Here's the code for the components I'm using:



Ext.define('MyApp.shared.RowContainer', {
extend: 'Ext.panel.Panel',
alias : 'widget.shared.rowcontainer',

requires: ['MyApp.shared.RowPanel'],

layout: { type: 'vbox', align: 'stretch' },
border: false,

initComponent: function() {
this.tbar = [{ text: 'Add Row', handler: Ext.bind(this.addRow, this, [true]) }];

this.callParent(arguments);

this.addEvents('rowadd','rowdelete');
},

addRow: function(removable) {
var that = this;

var row = this.add({
xtype : 'shared.rowpanel',
border : false,
flex : 1,
removable: removable
});

row.addColumn(false);

this.fireEvent('rowadd', this, row);

this.on('remove', function(rowContainer, row) {
rowContainer.fireEvent('rowdelete', rowContainer);
});
}
});




Ext.define('MyApp.shared.RowPanel', {
extend: 'Ext.panel.Panel',
alias: 'widget.shared.rowpanel',

layout : { type: 'hbox', align: 'stretch' },
border : false,
flex : 1,

initComponent: function() {
var that = this;

this.tbar = [
{
text : 'Remove Row',
itemId : 'removeRowBtn',
handler : Ext.bind(this.removeRow, this),
disabled: !this.removable
}
];

this.callParent(arguments);

this.on({
render: function() {
that.up('[xtype="shared.rowcontainer"]').on({
rowadd: { fn: that.onRowAdd, scope: that },
rowdelete: { fn: that.onRowDelete, scope: that }
});
},
beforeremove: function() {
that.up('[xtype="shared.rowcontainer"]').un('rowadd', that.onRowAdd, that);
that.up('[xtype="shared.rowcontainer"]').un('rowdelete', that.onRowDelete, that);
}
});
},

removeRow: function() {
this.ownerCt.remove(this);
},

onRowAdd: function(rowContainer, row) {
this.down('#removeRowBtn').enable();
},

onRowDelete: function(rowContainer) {
if (rowContainer.items == 1) {
this.down('#removeRowBtn').disable();
}
}
});


The code fails when you add a row, delete a row, and then try to add a row again. At that point, the onRowAdd() function in RowPanel fails because it runs for the row that was previously removed, so the down() function fails to return something. You'll notice that I have a 'beforeremove' listener to try to remove the events from the RowPanel, but it seems it's not working.

Any ideas? I'm assuming I'm just not understanding how to properly remove a component from its container. But I've never run into a case like this, probably because I seldom add listeners inside a component for an event from its container.

slemmon
19 Aug 2013, 1:28 PM
What about putting your un() in your removeRow method?



removeRow: function () {
var rowCt = this.up('[xtype="shared.rowcontainer"]')
rowCt.un('rowadd', rowCt.onRowAdd, rowCt);
rowCt.un('rowdelete', rowCt.onRowDelete, rowCt);
this.ownerCt.remove(this);
}