PDA

View Full Version : [CLOSED] Store update: Cannot call method 'hasCls' of null



paulc
May 08, 2012, 7:47 AM
Hi,

This was working until recently (I think it may have broken with the calendar updates). The scenario I have is a GridPanel and a DataView both using the same store. There is a button that switches visibility between DataView and GridPanel view.

The code I use to switch them is:


setView: function (view) {
switch (view) {
case "list":
App.gridPanelList.setVisible(true);
App.dataViewIcons.setVisible(false);
break;
case "icon":
App.gridPanelList.setVisible(false);
App.dataViewIcons.setVisible(true);
break;
}
},



By default the DataView is visible and the GridPanel is hidden. The exception is thrown when I attempt to update a record in the Store and the GridPanel hasn't been set to visible. If I switch between GridPanel/DataView at least once then the code works fine, it only throws the exception if the GridPanel has never been made visible.

The code I use to change the record in the Store is:



var contentItem = App.StoreContent.getById(id);
if (contentItem != null) {
contentItem.set("InBasket", true);
contentItem.commit();
}






The exception is thrown in:



onUpdate : function(store, record, operation, changedFieldNames) {
var me = this,
index,
newRow, oldRow,
oldCells, newCells, len, i,
columns, overItemCls,
isHovered, row;

if (me.rendered) {

index = me.store.indexOf(record);
columns = me.headerCt.getGridColumns();
overItemCls = me.overItemCls;




if (columns.length && index > -1) {
newRow = me.bufferRender([record], index)[0];
oldRow = me.all.item(index);
isHovered = oldRow.hasCls(overItemCls);Uncaught TypeError: Cannot call method 'hasCls' of null


oldRow.dom.className = newRow.className;
if(isHovered) {
oldRow.addCls(overItemCls);
}



oldCells = oldRow.query(this.cellSelector);
newCells = Ext.fly(newRow).query(this.cellSelector);
len = newCells.length;

row = oldCells[0].parentNode;
for (i = 0; i < len; i++) {

if (me.shouldUpdateCell(columns[i], changedFieldNames)) {
row.insertBefore(newCells[i], oldCells[i]);
row.removeChild(oldCells[i]);
}
}




me.selModel.refresh();
me.doStripeRows(index, index);
me.fireEvent('itemupdate', record, index, newRow);
}
}


},

Daniil
May 08, 2012, 11:20 AM
Hi,

I am unable to reproduce the problem using the example below.

Could you provide a full example to reproduce the problem?

What Ext.NET sources do you use?

Could you update from SVN and re-test? Does the problem persist?
http://svn.ext.net/premium/branches/2.0


Example

<%@ Page Language="C#" %>

<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>

<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!X.IsAjaxRequest)
{
Store store = this.GridPanel1.GetStore();
store.DataSource = new object[]
{
new object[] { "test1", "test2", "test3" },
new object[] { "test4", "test5", "test6" },
new object[] { "test7", "test8", "test9" },
};
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>Ext.NET v2 Example</title>

<script type="text/javascript">
var update = function () {
var store = App.GridPanel1.getStore(),
record = store.getAt(0);

record.set("test1", "new");
record.commit();
};
</script>
</head>
<body>
<ext:ResourceManager runat="server" />

<ext:GridPanel ID="GridPanel1" runat="server" AutoHeight="true">
<Store>
<ext:Store runat="server">
<Model>
<ext:Model runat="server">
<Fields>
<ext:ModelField Name="test1" />
<ext:ModelField Name="test2" />
<ext:ModelField Name="test3" />
</Fields>
</ext:Model>
</Model>
</ext:Store>
</Store>
<ColumnModel runat="server">
<Columns>
<ext:Column runat="server" Text="Test1" DataIndex="test1" />
<ext:Column runat="server" Text="Test2" DataIndex="test2" />
<ext:Column runat="server" Text="Test3" DataIndex="test3" />
</Columns>
</ColumnModel>
</ext:GridPanel>

<ext:Button runat="server" Text="Update">
<Listeners>
<Click Fn="update" />
</Listeners>
</ext:Button>
</body>
</html>

paulc
May 08, 2012, 11:31 AM
You need to set the GridPanel to hidden.

e.g.



<ext:GridPanel ID="GridPanel1" runat="server" AutoHeight="true" Hidden="True">



Hi,

I am unable to reproduce the problem using the example below.

Could you provide a full example to reproduce the problem?

What Ext.NET sources do you use?

Could you update from SVN and re-test? Does the problem persist?
http://svn.ext.net/premium/branches/2.0


Example

<%@ Page Language="C#" %>

<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>

<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!X.IsAjaxRequest)
{
Store store = this.GridPanel1.GetStore();
store.DataSource = new object[]
{
new object[] { "test1", "test2", "test3" },
new object[] { "test4", "test5", "test6" },
new object[] { "test7", "test8", "test9" },
};
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>Ext.NET v2 Example</title>

<script type="text/javascript">
var update = function () {
var store = App.GridPanel1.getStore(),
record = store.getAt(0);

record.set("test1", "new");
record.commit();
};
</script>
</head>
<body>
<ext:ResourceManager runat="server" />

<ext:GridPanel ID="GridPanel1" runat="server" AutoHeight="true">
<Store>
<ext:Store runat="server">
<Model>
<ext:Model runat="server">
<Fields>
<ext:ModelField Name="test1" />
<ext:ModelField Name="test2" />
<ext:ModelField Name="test3" />
</Fields>
</ext:Model>
</Model>
</ext:Store>
</Store>
<ColumnModel runat="server">
<Columns>
<ext:Column runat="server" Text="Test1" DataIndex="test1" />
<ext:Column runat="server" Text="Test2" DataIndex="test2" />
<ext:Column runat="server" Text="Test3" DataIndex="test3" />
</Columns>
</ColumnModel>
</ext:GridPanel>

<ext:Button runat="server" Text="Update">
<Listeners>
<Click Fn="update" />
</Listeners>
</ext:Button>
</body>
</html>

Daniil
May 08, 2012, 1:14 PM
Confirmed. I will report this bug to Sencha. Thanks for the report.

For now I can suggest the following fix/workaround, see GridView CustomConfig.

Example

<%@ Page Language="C#" %>

<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>

<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!X.IsAjaxRequest)
{
Store store = this.GridPanel1.GetStore();
store.DataSource = new object[]
{
new object[] { "test1", "test2", "test3" },
new object[] { "test4", "test5", "test6" },
new object[] { "test7", "test8", "test9" },
};
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>Ext.NET v2 Example</title>

<script type="text/javascript">
var myOnUpdate = function(store, record, operation, changedFieldNames) {
var me = this,
index,
newRow, oldRow,
oldCells, newCells, len, i,
columns, overItemCls,
isHovered, row;

if (me.rendered && !me.panel.hidden) { // added '&& !me.panel.hidden'

index = me.store.indexOf(record);
columns = me.headerCt.getGridColumns();
overItemCls = me.overItemCls;

// If we have columns which may *need* updating (think lockable grid child with all columns either locked or unlocked)
// and the changed record is within our view, then update the view
if (columns.length && index > -1) {
newRow = me.bufferRender([record], index)[0];
oldRow = me.all.item(index);
isHovered = oldRow.hasCls(overItemCls);
oldRow.dom.className = newRow.className;
if(isHovered) {
oldRow.addCls(overItemCls);
}

// Replace changed cells in the existing row structure with the new version from the rendered row.
oldCells = oldRow.query(this.cellSelector);
newCells = Ext.fly(newRow).query(this.cellSelector);
len = newCells.length;
// row is the element that contains the cells. This will be a different element from oldRow when using a rowwrap feature
row = oldCells[0].parentNode;
for (i = 0; i < len; i++) {
// If the field at this column index was changed, replace the cell.
if (me.shouldUpdateCell(columns[i], changedFieldNames)) {
row.insertBefore(newCells[i], oldCells[i]);
row.removeChild(oldCells[i]);
}
}

// Maintain selection after update
// TODO: Move to approriate event handler.
me.selModel.refresh();
me.doStripeRows(index, index);
me.fireEvent('itemupdate', record, index, newRow);
}
}
};
</script>
</head>
<body>
<ext:ResourceManager runat="server" />

<ext:GridPanel
ID="GridPanel1"
runat="server"
AutoHeight="true"
Hidden="true">
<Store>
<ext:Store runat="server">
<Model>
<ext:Model runat="server">
<Fields>
<ext:ModelField Name="test1" />
<ext:ModelField Name="test2" />
<ext:ModelField Name="test3" />
</Fields>
</ext:Model>
</Model>
</ext:Store>
</Store>
<ColumnModel runat="server">
<Columns>
<ext:Column runat="server" Text="Test1" DataIndex="test1" />
<ext:Column runat="server" Text="Test2" DataIndex="test2" />
<ext:Column runat="server" Text="Test3" DataIndex="test3" />
</Columns>
</ColumnModel>
<View>
<ext:GridView runat="server">
<CustomConfig>
<ext:ConfigItem Name="onUpdate" Value="myOnUpdate" Mode="Raw" />
</CustomConfig>
</ext:GridView>
</View>
</ext:GridPanel>

<ext:Button runat="server" Text="Update">
<Listeners>
<Click Handler="App,GridPanel1.getStore().getAt(0).set('test1', 'new value');" />
</Listeners>
</ext:Button>
</body>
</html>

Daniil
May 08, 2012, 1:38 PM
I've reported the bug to Sencha.
http://www.sencha.com/forum/showthread.php?202939

Lets wait what they will answer. I will update the thread.

paulc
May 08, 2012, 2:08 PM
Thanks Daniil, I can confirm your workaround is working for me.

paulc
Jul 02, 2012, 9:20 AM
Thanks Daniil, I can confirm your workaround is working for me.

Hi, I see Sencha have fixed this issue. Has the fix made it into the current build in branches/2.0 ?

Vladimir
Jul 02, 2012, 9:49 AM
Not yet,
Once ExtJS 4.1.1 will be released then we will include it to Ext.Net.
ExtJS 4.1.1 will be included to Ext.Net 2.1

Daniil
Aug 27, 2012, 7:59 AM
ExtJS 4.1.1 and, respectively, the fix have been included into the 2.1 branch.

Thanks again for the report!