PDA

View Full Version : [OPEN] [#369] Bug with gridpanel on tabs



alex303
Nov 01, 2013, 12:29 PM
I have TabPabel with two tabs, each of which is GridPanel. By pressing a button I try to load the data in the grids.

The complete project for VS2010 can be downloaded at http://www.fileswap.com/dl/B9aOLl3nYa/

The key snippets:

View


@using System.Collections.ObjectModel
@using Ext.Net
@using Ext.Net.MVC
@using ScriptMode = Ext.Net.ScriptMode

@{
var ext = Html.X();
}

@ext.ResourceManager().ScriptMode(ScriptMode.Debug ).SourceFormatting(true)

<script type="text/javascript">

var reloadGrid = function (name, data, config, grid) {
var control = grid;
var controlId = control.getId();
console.log("reload begin: " + controlId);
var store = control.getStore();
store.proxy.extraParams = { name: controlId };
store.load({
scope: this,
callback: function (records, operation, success) {
console.log("reload complete: " + controlId + " (" + success + ")");
if (success) {
var sm = control.getSelectionModel();
sm.clearSelections();
sm.select(0);
}
}
});
}

</script>

@functions {

private AbstractComponent CreateGrid(string gridId)
{
var ext = Html.X();
return ext.GridPanel()
.ID(gridId)
.Title(gridId)
.ColumnModel(
ext.Column().Text("Id").DataIndex("ID"),
ext.Column().Text("Name").DataIndex("NAME"),
ext.Column().Text("Value").DataIndex("VALUE"),
ext.Column().Text("Date").DataIndex("DATE")

)
.SelectionModel(
ext.CheckboxSelectionModel().Mode(SelectionMode.Mu lti).ShowHeaderCheckbox(true).PruneRemoved(false)
)
.MessageBusListeners(new MessageBusListener
{
Name = "Test.Button.*",
Handler = "reloadGrid(name, data, config, this);"
})
.Store(
ext.Store()
.ItemID("ID")
.RemoteFilter(true).RemoteSort(true).RemotePaging( true).RemoteGroup(true)
.Buffered(true)
// With default value (25) loading will hang up... http://forums.ext.net/showthread.php?26505-OPEN-348-Infinity-Scrolling
.PageSize(50)
.AutoLoad(false)
.Model(
ext.Model()
.Name(gridId+"_model")
.Fields(
new ModelField("ID", ModelFieldType.Int),
new ModelField("NAME", ModelFieldType.String),
new ModelField("VALUE", ModelFieldType.Int),
new ModelField("DATE", ModelFieldType.Date)
)
)
.Proxy(
ext.AjaxProxy()
.Url(Url.Action("GetGridData"))
.Reader(ext.JsonReader().Root("data").TotalProperty("total").IDProperty("ID"))
.ActionMethods(methods => methods.Read = HttpMethod.POST)
)
);
}

}

@{
var grids = new Collection<AbstractComponent>
{
CreateGrid("Grid1"),
CreateGrid("Grid2"),
};
}

@(ext.Viewport()
.ID("viewPort")
.Layout(LayoutType.Border)
.Items(ext.Panel()
.Region(Region.North)
.Items(
ext.Button()
.Text("Reload")
.Listeners(listeners => { listeners.Click.BroadcastOnBus = "Test.Button.Click"; })),
ext.TabPanel()
.Region(Region.Center)
.Items(grids)
))


Controller


using System;
using System.Data;
using System.Web.Mvc;
using Ext.Net.MVC;

namespace TwoGrids.Controllers
{
public class HomeController : Controller
{
private const int CMaxRowCount = 1001; // With value 1000 it will crashed then scroll down at end

public ActionResult Index()
{
return View();
}

[HttpPost]
public StoreResult GetGridData(string name, int? page, int? start, int limit)
{
var dataTable = GetData(name, start.HasValue ? start.Value : 0, limit);
var result = this.Store(dataTable);
result.Total = CMaxRowCount;
return result;
}

private static DataTable GetData(string name, int firstRow, int maxRows)
{
var dataTable = new DataTable();
dataTable.Columns.AddRange(new[]
{
new DataColumn("ID", typeof (int)),
new DataColumn("NAME", typeof (string)),
new DataColumn("VALUE", typeof (int)),
new DataColumn("DATE", typeof (DateTime))
});

var randow = new Random();

for (var i = firstRow + 1; i <= firstRow + maxRows; i++)
{
var row = dataTable.NewRow();
row["ID"] = i;
row["NAME"] = name + "_" + i;
row["VALUE"] = randow.Next(100, 200);
row["DATE"] = DateTime.Now;

dataTable.Rows.Add(row);
}

return dataTable;
}
}
}


There are two bugs, but as I prepared one example, I will describe both of them in one post.

1. Grid on inactive tab is not updated. There is an error somewhere in the javascripts, as evidenced by FireBug.

Steps for localization:
1.1 Open Page
1.2 Press the button
1.3 Go to the second tab. Catch the bug - 'rows' is undefined (see attached screenshot).
7151

UPDATE:
In additional try to do this:
1.1 Open Page
1.2 DON'T PUSH BUTTON!
1.3 Go to Tab2, Grid is empty. It's ok.
1.4 Come back at Tab1
1.5 PUSH THE BUTTON!
1.6 Go to tab2, some records are there... but try to scroll.... it only 66 records, and grid will not fetch any more.... well thrid bug...


2. Please note, the grid is buffered.
When Total (from json response) divided by the PageSize no residue, when scrolling to the end we get an error. (Changing CMaxRowCount from 1000 to 1001 at my example will make it works).
Steps for localization:
1.1 Check that CMaxRowCount is 1000 - total number in dataset
1.2 Check that grids PageSize is 100
1.3 Open page
1.4 Press the button
1.5 Scroll down by the scroller at the end. All rows wont be loaded, it will crash at line 992 (screenshot attached).
7152

Daniil
Nov 01, 2013, 3:59 PM
Hi @alex303,

Yes, unfortunately, there are problems with grid buffered rendering.

I think the first two problems can be related to these Issues:
https://github.com/extnet/Ext.NET/issues/270
https://github.com/extnet/Ext.NET/issues/308
https://github.com/extnet/Ext.NET/issues/355

The third problem might be related to this one:
https://github.com/extnet/Ext.NET/issues/288

Thank you for a test sample. We should ensure it is not a new case.

By the way, what is the Ext.NET version you are working with?

alex303
Nov 01, 2013, 4:11 PM
Daniil,

Thx, I will read those post...

> By the way, what is the Ext.NET version you are working with?

Latest version from SVN... I just build it from sources


upd
---
I spent a few hours on debugging Sencha's source code and now the cause of most bugs is clear to me. Incorrect behavior is a consequence of the fact that a lot of logic of BufferedRender depends on the size of DOM-elements. So as an invisible dom-elements sizes are equal to 0, I have seen the division by zero, Infinities and other "cute" things. So stupid.

Unfortunately, this is not just a little bug, it's a total defect when BufferedRender is invisible (point of start - method onViewResize will set viewSize to Infinity due divizion by rowHeight which is zero). And the saddest thing is that Sencha doesn't want to fix it... I have read their forum... such bugs have a long story. Very strange and incomprehensible behavior for a commercial project. Especially for such importand and usefull thing like pageless grid with partial fetching.

In my case, I have got a solution of most problems by implementing some kind of "pending updates". Not very elegant, but seems to be working.

Daniil
Nov 04, 2013, 6:12 AM
I totally agree with you. It is absolutely incomprehensible why such big bugs with key features take so much time to fix (or even not fixed at all).

I added this thread for references in this Issue:
https://github.com/extnet/Ext.NET/issues/270

Do you mind we close this thread? If some new info comes up, we will update it with a new post.

Daniil
Nov 04, 2013, 11:02 AM
2. Please note, the grid is buffered.
When Total (from json response) divided by the PageSize no residue, when scrolling to the end we get an error. (Changing CMaxRowCount from 1000 to 1001 at my example will make it works).
Steps for localization:
1.1 Check that CMaxRowCount is 1000 - total number in dataset
1.2 Check that grids PageSize is 100
1.3 Open page
1.4 Press the button
1.5 Scroll down by the scroller at the end. All rows wont be loaded, it will crash at line 992 (screenshot attached).
7152

Could you, please, try this fix?


Fix

Ext.view.Table.override({
renderRow: function(record, rowIdx, out) {
var me = this,
isMetadataRecord = rowIdx === -1,
selModel = me.selModel,
rowValues = me.rowValues,
itemClasses = rowValues.itemClasses,
rowClasses = rowValues.rowClasses,
cls,
rowTpl = me.rowTpl;

// Set up mandatory properties on rowValues
rowValues.record = record;
rowValues.recordId = record.internalId;
rowValues.recordIndex = rowIdx;
rowValues.rowId = me.getRowId(record);
rowValues.itemCls = rowValues.rowCls = '';
if (!rowValues.columns) {
rowValues.columns = me.ownerCt.columnManager.getColumns();
}

itemClasses.length = rowClasses.length = 0;

// If it's a metadata record such as a summary record.
// So do not decorate it with the regular CSS.
// The Feature which renders it must know how to decorate it.
if (!isMetadataRecord) {
itemClasses[0] = Ext.baseCSSPrefix + "grid-row";
if (selModel && selModel.isRowSelected) {
//if (selModel.isRowSelected(rowIdx + 1)) { // wrong
if (selModel.isRowSelected(record)) { // or if (selModel.isRowSelected(rowIdx)) {
itemClasses.push(me.beforeSelectedItemCls);
}
if (selModel.isRowSelected(record)) {
itemClasses.push(me.selectedItemCls);
}
}

if (me.stripeRows && rowIdx % 2 !== 0) {
rowClasses.push(me.altRowCls);
}

if (me.getRowClass) {
cls = me.getRowClass(record, rowIdx, null, me.dataSource);
if (cls) {
rowClasses.push(cls);
}
}
}

if (out) {
rowTpl.applyOut(rowValues, out);
} else {
return rowTpl.apply(rowValues);
}
}
});

alex303
Nov 05, 2013, 8:12 AM
Could you, please, try this fix?

I did not test it deeply, but at first glance, works great! Thank you.


Do you mind we close this thread?

I have no reason to object.

Daniil
Nov 05, 2013, 8:38 AM
I did not test it deeply, but at first glance, works great! Thank you.

Nice, thank you for confirming. I committed the fix to the SVN trunk in revision 5466.

Also created an Issue to review after next ExtJS update.
https://github.com/extnet/Ext.NET/issues/369

Daniil
Feb 17, 2014, 1:38 PM
Hi @alex303,

It turned out that my fix causes another issue.
http://forums.ext.net/showthread.php?28089

Could you, please, try this fix instead?

Fix

Ext.view.Table.override({
renderRow: function(record, rowIdx, out) {
var me = this,
isMetadataRecord = rowIdx === -1,
selModel = me.selModel,
rowValues = me.rowValues,
itemClasses = rowValues.itemClasses,
rowClasses = rowValues.rowClasses,
cls,
rowTpl = me.rowTpl;

rowValues.record = record;
rowValues.recordId = record.internalId;
rowValues.recordIndex = rowIdx;
rowValues.rowId = me.getRowId(record);
rowValues.itemCls = rowValues.rowCls = '';
if (!rowValues.columns) {
rowValues.columns = me.ownerCt.columnManager.getColumns();
}

itemClasses.length = rowClasses.length = 0;

if (!isMetadataRecord) {
itemClasses[0] = Ext.baseCSSPrefix + "grid-row";
if (selModel && selModel.isRowSelected) {

if ((rowIdx + 1) < selModel.store.getTotalCount()) {
if (selModel.isRowSelected(rowIdx + 1)) {
itemClasses.push(me.beforeSelectedItemCls);
}
}

if (selModel.isRowSelected(record)) {
itemClasses.push(me.selectedItemCls);
}
}

if (me.stripeRows && rowIdx % 2 !== 0) {
rowClasses.push(me.altRowCls);
}

if (me.getRowClass) {
cls = me.getRowClass(record, rowIdx, null, me.dataSource);
if (cls) {
rowClasses.push(cls);
}
}
}

if (out) {
rowTpl.applyOut(rowValues, out);
} else {
return rowTpl.apply(rowValues);
}
}
});

Daniil
Feb 20, 2014, 8:43 AM
I decided to commit the fix. Revision #5673. It will go to the v2.5 release.

Please report if you face any issues with the new fix.