Blazor Grid Remote Data Operations
By default, the IgbGrid
uses its own logic for performing data operations.
You can perform these tasks remotely and feed the resulting data to the IgbGrid
by taking advantage of certain inputs and events, which are exposed by the IgbGrid
.
Infinite Scroll
A popular design for scenarios requiring fetching data by chunks from an end-point is the so-called infinite scroll. For data grids, it is characterized by continuous increase of the loaded data triggered by the end-user scrolling all the way to the bottom. The next paragraphs explain how you can use the available API to easily achieve infinite scrolling in IgbGrid
.
To implement infinite scroll, you have to fetch the data in chunks. The data that is already fetched should be stored locally and you have to determine the length of a chunk and how many chunks there are. You also have to keep a track of the last visible data row index in the grid. In this way, using the StartIndex
and ChunkSize
properties, you can determine if the user scrolls up and you have to show them already fetched data or scrolls down and you have to fetch more data from the end-point.
The first thing to do is fetch the first chunk of the data. Setting the TotalItemCount
property is important, as it allows the grid to size its scrollbar correctly.
@code {
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
var grid = this.grid;
grid.IsLoading = true;
double dataViewSize = 480.0 / 50.0;
this.PageSize = Convert.ToInt32(Math.Floor(dataViewSize * 1.5));
var data = await GetDataRemote(1, this.PageSize);
this.CachedData = data;
this.LocalData = this.CachedData;
grid.TotalItemCount = (this.PageSize * this.Page) + 1;
double pageCount = Math.Ceiling((double)this.TotalItems / (double)this.PageSize);
this.TotalPageCount = (int)pageCount;
grid.IsLoading = false;
StateHasChanged();
}
}
}
Additionally, you have to subscribe to the DataPreLoad
output, so that you can provide the data needed by the grid when it tries to display a different chunk, rather than the currently loaded one. In the event handler, you have to determine whether to fetch new data or return data, that's already cached locally.
<IgbGrid AutoGenerate="false"
Height="480px"
Name="grid"
Id="grid"
Data="LocalData"
@ref="grid"
DataPreLoad="OnDataPreLoad">
<IgbColumn Name="ID"
Field="ProductID"
Header="ID">
</IgbColumn>
<IgbColumn Name="ProductName"
Field="ProductName"
Header="Product Name">
</IgbColumn>
<IgbColumn Name="QuantityPerUnit"
Field="QuantityPerUnit"
Header="Quantity Per Unit">
</IgbColumn>
<IgbColumn Name="UnitPrice"
Field="UnitPrice"
Header="Unit Price">
</IgbColumn>
<IgbColumn Name="OrderDate"
Field="OrderDate"
Header="Order Date">
</IgbColumn>
<IgbColumn Name="Discontinued"
Field="Discontinued"
Header="Discontinued">
</IgbColumn>
</IgbGrid>
@code {
private IgbGrid grid;
public async void OnDataPreLoad(IgbForOfStateEventArgs e)
{
int chunkSize = (int)e.Detail.ChunkSize;
int startIndex = (int)e.Detail.StartIndex;
int totalCount = (int)this.grid.TotalItemCount;
bool isLastChunk = totalCount == startIndex + chunkSize;
// when last chunk reached load another page of data
if (isLastChunk)
{
if (this.TotalPageCount == this.Page)
{
this.LocalData = this.CachedData.Skip(startIndex).Take(chunkSize).ToList();
return;
}
// add next page of remote data to cache
this.grid.IsLoading = true;
this.Page++;
var remoteData = await GetDataRemote(this.Page, this.PageSize);
this.CachedData.AddRange(remoteData);
var data = this.CachedData.Skip(startIndex).Take(chunkSize);
this.LocalData = data.ToList();
this.grid.IsLoading = false;
this.grid.TotalItemCount = Math.Min(this.Page * this.PageSize, this.TotalItems);
}
else
{
var data = this.CachedData.Skip(startIndex).Take(chunkSize).ToList();
this.LocalData = data;
}
}
}
Infinite Scroll Demo
Remote Paging
The paging feature can operate with remote data. In order to demonstrate this let's first declare our service that will be responsible for data fetching. We will need the count of all data items in order to calculate the page count. This logic will be added to our service.
As Blazor Server is already a remote instance, unlike the demos in the other platforms we do not need to set another remote instance for the data, as the data is already remote. In order to do remote paging, we just need to set a couple of methods ins the data class
public Task<List<NwindDataItem>> GetData(int index, int perPage)
{
var itemsToReturn = items.Skip(index).Take(perPage).ToList();
return Task.FromResult(itemsToReturn);
}
public Task<int> GetDataLength()
{
return Task.FromResult(items.Count);
}
After declaring the service, we need to create a component, which will be responsible for the IgbGrid
construction and data subscription.
First we should load some data to the grid. It is best to do after the grid has been rendered to avoid any timing issues.
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await Paginate(0, PerPage);
totalRecordsCount = await NwindDataService.GetDataLength();
StateHasChanged();
}
}
After that we just need to bind the paging events to our custom methods, and remote paging is set:
<IgbPaginator @ref="pager" PageChange="OnPageChange" PerPageChange="OnPerPageChange" TotalRecords="totalRecordsCount"></IgbPaginator>
....
@code {
private async void OnPerPageChange(IgbNumberEventArgs e)
{
PerPage = e.Detail;
await Paginate(0, e.Detail);
}
private async void OnPageChange(IgbNumberEventArgs e)
{
await Paginate(e.Detail, PerPage);
}
...
private async Task Paginate(double page, double perPage)
{
this.page = page;
double skip = this.page * PerPage;
double top = PerPage;
try
{
data = await NwindDataService.GetData(Convert.ToInt32(skip), Convert.ToInt32(perPage));
isLoading = false;
UpdateUI();
}
catch (Exception ex)
{
Console.Error.WriteLine($"Error fetching data: {ex.Message}");
}
}
}
For further reference please check the full demo bellow:
Grid Remote Paging Demo
Known Issues and Limitations
- When the grid has no
PrimaryKey
set and remote data scenarios are enabled (when paging, sorting, filtering, scrolling trigger requests to a remote server to retrieve the data to be displayed in the grid), a row will lose the following state after a data request completes:
- Row Selection
- Row Expand/collapse
- Row Editing
- Row Pinning
API References
Additional Resources
- Paging
- Virtualization and Performance
- Filtering
- Sorting
- Summaries
- Column Moving
- Column Pinning
- Column Resizing
- Selection
Our community is active and always welcoming to new ideas.