Jul 26, 2012, 12:15 PM
[FIXED] [2.2] Destroy of Locking Grid Panel - SelectionMemory and SelectionSubmit
Hi there,
I found a bug in the latest 2.0 relesase. This bug (silent crash) occurs while destruction of the plugins of a locked grid.
It is special because it doesn't happen in a normal use case.
It could still have an effect in other sittuation and is definitely a bug, so I decided to share it.
First of all, the Code. Here I create a locking (column) grid and destroy it after 2 seconds:
Set a conditional breakpoint (this.selModel === undefined) on the first line of SelectionMemory::destroy source. Load the page again.
You will see that the plugin is destroyed an will crash there. It seem like that doesn't matter because Ext.net.ResourceMgr.destroyCmp is catching the exception. But you will notice that the grid is still not destroy completely (App.grid is still there).
Let's go further ;-) If you try to recreate a Component with the ID grid, then AbstractComponent tries to destroy the existing component because it's still there. But this time it does crash because it calls destroy directly instead Ext.net.ResourceMgr.destroyCmp.
So again: Nobody would ever notice since nobody destroys components on his own. But I do something more dynamic and it's definitely a bug.
Here's my work around. Maybe not the cleanest way but it works:
Viktor
I found a bug in the latest 2.0 relesase. This bug (silent crash) occurs while destruction of the plugins of a locked grid.
It is special because it doesn't happen in a normal use case.
It could still have an effect in other sittuation and is definitely a bug, so I decided to share it.
First of all, the Code. Here I create a locking (column) grid and destroy it after 2 seconds:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="Mx.Ext.Test.WebForm1" %>
<%@ Register assembly="Ext.Net" namespace="Ext.Net" tagprefix="ext" %>
<script runat="server">
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
manager.ScriptMode = Ext.Net.ScriptMode.Debug;
if (!X.IsAjaxRequest)
{
List<object> data = new List<object>();
for (int i = 0; i < 10; i++)
{
data.Add(new object[] { "locked" + i, "notlocked" + i });
}
store.DataSource = data;
store.DataBind();
}
}
</script>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script type="text/javascript">
Ext.defer(function () {
Ext.net.ResourceMgr.destroyCmp('grid');
}, 2000);
</script>
</head>
<body>
<form id="form1" runat="server">
<ext:ResourceManager runat="server" ID="manager" />
<ext:Store runat="server" ID="store">
<Model>
<ext:Model runat="server">
<Fields>
<ext:ModelField Name="locked" />
<ext:ModelField Name="notlocked" />
</Fields>
</ext:Model>
</Model>
</ext:Store>
<ext:GridPanel runat="server" ID="grid" StoreID="store">
<ColumnModel>
<Columns>
<ext:Column runat="server" ID="Column1" DataIndex="locked" Locked="true" />
<ext:Column runat="server" ID="Column2" DataIndex="notlocked" />
</Columns>
</ColumnModel>
</ext:GridPanel>
</form>
</body>
</html>
Load the page, open Firebug, search for SelectionMemory::destroy source (serach for Ext.define('Ext.grid.plugin.SelectionMemory').Set a conditional breakpoint (this.selModel === undefined) on the first line of SelectionMemory::destroy source. Load the page again.
You will see that the plugin is destroyed an will crash there. It seem like that doesn't matter because Ext.net.ResourceMgr.destroyCmp is catching the exception. But you will notice that the grid is still not destroy completely (App.grid is still there).
Let's go further ;-) If you try to recreate a Component with the ID grid, then AbstractComponent tries to destroy the existing component because it's still there. But this time it does crash because it calls destroy directly instead Ext.net.ResourceMgr.destroyCmp.
So again: Nobody would ever notice since nobody destroys components on his own. But I do something more dynamic and it's definitely a bug.
Here's my work around. Maybe not the cleanest way but it works:
Ext.grid.plugin.SelectionMemory.override({
destroy: function () {
var me = this;
if (me.selModel) {
me.selModel.un("select", me.onMemorySelect, me);
me.selModel.un("deselect", me.onMemoryDeselect, me);
}
if (me.grid) {
me.grid.store.un("remove", me.onStoreRemove, me);
me.grid.getView().un("refresh", me.memoryReConfigure, me, { single: true });
me.grid.getView().onMaskBeforeShow = me.grid.getView()._onMaskBeforeShow;
}
if (me.selModel) {
me.selModel.onSelectChange = me.selModel._onSelectChange;
}
}
});
Ext.grid.plugin.SelectionSubmit.override({
destroy: function () {
var me = this;
if (me.hField && me.hField.rendered) {
me.hField.destroy();
me.store.un("load", me.doSelection, me, { single: true, delay: 100 });
}
if (me.grid) {
var sm = me.grid.getSelectionModel();
if (sm instanceof Ext.selection.CellModel) {
sm.un("deselect", me.updateSelection, me, { buffer: 1 });
sm.un("select", me.updateSelection, me, { buffer: 1 });
} else {
sm.un("selectionchange", me.updateSelection, me, { buffer: 10 });
}
me.grid.getView().un("afterrender", me.renderHiddenField, me);
me.grid.store.un("clear", me.clearField, me);
}
}
});
RegardsViktor
Last edited by Daniil; Nov 30, 2012 at 4:00 PM.
Reason: [FIXED] [2.2]