Hello again, Mr. Huang!
They are really close from having the grid properly reload! We've recently had some questions very similar to this in the forums, but related to Ext.NET 5. And the answer and discussion there, although around the same logic, doesn't really apply here.
With the test case provided, it was easy to see the issue and reproduce it. And as for the fix, the paging does not really mingle well (or was designed) with frequent data change updates in mind, but rather a static data set. We'll get to that later.
What's needed to properly update the store data
when local paging with remote data is used, is updating the memory proxy's full internal dataset. Local paging through the memory proxy is done by storing the actual data somewhere and loading the grid store records in
chunks,
pageSize
elements a time. Thus, if you just add data straight into the store, what you get is what is seen in the test case provided: the full data set.
Instead, update the memory proxy's internal data. Notwithstanding, there will be cases that we should treat when reloading the data, as the user may be in a page that ceased to exist, or an empty grid that gets fresh data after a reload -- or simply a grid that gains an extra page on the fresh dataset.
I have changed your test case to accomodate (hopefully) all these functionality aspects.
index.cshtml
@page "{handler?}"
@model Ext.Net.Examples.Pages.samples.gridpanel.miscellaneous.refresh_store.IndexModel
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>
Refresh Grid Store with Direct Event - Ext.NET Examples
</title>
<script>
var template = '<span style="color:{0};">{1}</span>';
var change = function (value) {
return Ext.String.format(template, (value > 0) ? "green" : "red", value);
};
var pctChange = function (value) {
return Ext.String.format(template, (value > 0) ? "green" : "red", value + "%");
};
var reloadCurrentPage = function() {
var store = App.companyStore2,
curPage = store.currentPage < 1 ? 1 : store.currentPage;
while (true) {
if (curPage >= 0) {
store.loadPage(curPage--);
if (store.count() > 0 || curPage < 0) return;
}
}
}
var reloadPagingStore = function (dataJson) {
App.companyStore2.proxy.data = Ext.decode(dataJson).result;
reloadCurrentPage();
}
</script>
</head>
<body>
<h1>
Refresh Grid Store with Direct Event
</h1>
<!-- Configure a Store -->
<ext-store data="Model.GridData" storeId="companyStore2" pageSize="10">
<fields>
<ext-dataField name="company" />
<ext-numberDataField name="price" />
<ext-numberDataField name="change" />
<ext-numberDataField name="pctChange" />
<ext-dateDataField name="lastChange" dateFormat="yyyy-MM-dd hh:mm:ss" />
</fields>
<proxy>
<ext-memoryProxy enablePaging="true" />
</proxy>
</ext-store>
<!-- Configure a GridPanel and reference the Store above -->
<ext-gridPanel
id="GridPanel1"
title="Array Grid"
width="960"
height="640"
frame="true"
store="companyStore2">
<columns>
<ext-column text="Company" dataIndex="company" flex="1" />
<ext-column text="Price" dataIndex="price" renderer="Ext.util.Format.usMoney" />
<ext-column text="Change" dataIndex="change" renderer="change" />
<ext-column text="Change %" dataIndex="pctChange" renderer="pctChange" />
<ext-dateColumn
text="Last Updated"
dataIndex="lastChange"
width="140"
format="hh:mm:ss"
/>
</columns>
<tbar>
<ext-toolbar>
<items>
<ext-button text="Print" iconCls="x-md md-icon-print" handler="this.up('grid').print();" />
<ext-button text="Reload Data">
<directEvents>
<click pageHandler="RefreshGrid" success="reloadPagingStore(response.responseText);" method="POST" />
</directEvents>
</ext-button>
</items>
</ext-toolbar>
</tbar>
<bbar>
<ext-pagingToolbar displayInfo="true"/>
</bbar>
</ext-gridPanel>
</body>
</html>
index.cshtml.cs
using Ext.Net.Core;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Collections.Generic;
using System;
using System.Linq;
namespace Ext.Net.Examples.Pages.samples.gridpanel.miscellaneous.refresh_store
{
public class IndexModel : PageModel
{
private static string now
{
get => DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");
}
public List<object> GridData => new List<object>
{
new object[] { "3m Co", 71.72, 0.02, 0.03, now },
new object[] { "Alcoa Inc", 29.01, 0.42, 1.47, now },
new object[] { "Altria Group Inc", 83.81, 0.28, 0.34, now },
new object[] { "American Express Company", 52.55, 0.01, 0.02, now },
new object[] { "American International Group, Inc.", 64.13, 0.31, 0.49, now },
new object[] { "AT&T Inc.", 31.61, -0.48, -1.54, now },
new object[] { "Boeing Co.", 75.43, 0.53, 0.71, now },
new object[] { "Caterpillar Inc.", 67.27, 0.92, 1.39, now },
new object[] { "Citigroup, Inc.", 49.37, 0.02, 0.04, now },
new object[] { "E.I. du Pont de Nemours and Company", 40.48, 0.51, 1.28, now },
new object[] { "Exxon Mobil Corp", 68.1, -0.43, -0.64, now },
new object[] { "General Electric Company", 34.14, -0.08, -0.23, now },
new object[] { "General Motors Corporation", 30.27, 1.09, 3.74, now },
new object[] { "Hewlett-Packard Co.", 36.53, -0.03, -0.08, now },
new object[] { "Honeywell Intl Inc", 38.77, 0.05, 0.13, now },
new object[] { "Intel Corporation", 19.88, 0.31, 1.58, now },
new object[] { "International Business Machines", 81.41, 0.44, 0.54, now },
new object[] { "Johnson & Johnson", 64.72, 0.06, 0.09, now },
new object[] { "JP Morgan & Chase & Co", 45.73, 0.07, 0.15, now },
new object[] { "McDonald's Corporation 99", 36.76, 0.86, 2.40, now },
new object[] { "Merck & Co., Inc.", 40.96, 0.41, 1.01, now },
new object[] { "Microsoft Corporation", 25.84, 0.14, 0.54, now },
new object[] { "Pfizer Inc", 27.96, 0.4, 1.45, now },
new object[] { "The Coca-Cola Company", 45.07, 0.26, 0.58, now },
new object[] { "The Home Depot, Inc.", 34.64, 0.35, 1.02, now },
new object[] { "The Procter & Gamble Company", 61.91, 0.01, 0.02, now },
new object[] { "United Technologies Corporation", 63.26, 0.55, 0.88, now },
new object[] { "Verizon Communications", 35.57, 0.39, 1.11, now },
new object[] { "Wal-Mart Stores, Inc.", 45.45, 0.73, 1.63, now }
};
public void OnGet()
{
}
private static int _removeCnt;
private int removeCnt
{
get
{
if (_removeCnt > (GridData.Count - 1)) _removeCnt = -1;
return ++_removeCnt;
}
}
public IActionResult OnPostRefreshGrid() => this.Direct(GridData.Skip(removeCnt));
}
}
In summary, the changes in
index.cshtml:
- adds
reloadCurrentPage()
and
reloadPagingStore()
client-side helper functions
- updates the
success
handler in the
Reload Data button's click direct event to use these helpers instead
As for
index.cshtml.cs
- turns the
GridData
"field" into a "property" (in C# naming conventions)
- simulate data removal every time data is reloaded like original, but once data becomes empty, it will cycle back to the full initial dataset.
Now you can check the example, how it goes back from page 3 to page 2 when switching to page 3 and removing all records for that page. Also, when the last record is removed and an additional reload is triggered (to get a full dataset), it will switch to the first page and report the correct number of pages "refilled" into the grid.
All this was necessary because, as said in the beginning of this post, local paging with remote data is not really meant (out of the box) to handle dynamic data changes reflected from the server.
You'll probably notice how the paging behaves better related to data changes in the
Grid Panel > Paging and Sorting > Page example, which uses full paged (and sorted) data from server, such that we'd never need to store a local (client-side) copy of the full dataset. Also, there the paging toolbar's
Refresh button works! You may want to either hide or change the default behavior of the reload button in the paging toolbar to keep the approach you started with.
For an average amount of data, the approach you're aiming for should be good enough. If the frequency of data fetching from the server is high though, maybe you're better off with the alternative in the example pointed in the paragraph above. That is, if for every record removed/added you need to pull the full data from the server, maybe fetching just the exact page would work best, especiially if the users of your application would be often removing data or expecting new data to come from the server.
Hope this clarifies all your questions about the paging misbehavior! Let us know if there's anything left to explain.