New to Telerik UI for Blazor? Start a free 30-day trial
Get Filtered and Sorted Data from Grid
Updated over 6 months ago
Environment
| Product | Grid for Blazor, TreeList for Blazor |
Description
This KB article answers the following questions. All of them revolve around the Grid table rows, which the component is currently displaying to the user.
- How to obtain the filtered data in the Grid? This applies to filtering and the
SearchBox. - How do I know the filtered item count? How to get how many rows are in the filtered Grid?
- How to find only the used (displayed) items the Grid data list?
- How can I get the Grid data after filtering or sorting?
- How to get the sorted data in the Grid? How to get the Grid items in the order that is on the user screen?
- Is a way to get current Grid state data?
- How to find the next or previous data row if the user has sorted the Grid? In this case the original table row index doesn't match the index in the sorted data.
- How to get the clicked row index if the Grid is sorted or filtered?
Solution
The solution is different when:
Things to consider:
- When using
OnRead, there will be less custom code and no need to repeat the internal Grid data operations manually. - When the Grid data is grouped, the
DataSourceResult.Datacollection contains members of typeAggregateFunctionsGroupinstead of Grid model class objects.
When Using Data Parameter
- Obtain the Grid state in the Grid
OnStateChangedevent or with the GridGetState()method. The exact approach depends on if you want to get the current visible Grid data automatically or on demand. - Create a new
DataSourceRequestobject. Populate its properties with the respective information from theGridStateobject. Note that theFiltersproperty of theDataSourceRequestwill have to include filter descriptors from twoGridStateproperties -FilterDescriptorsandSearchFilter. - (optional) If you want to get the currently filtered and sorted data from all Grid pages, do not set the
Page,PageSize, andSkipproperties of theDataSourceRequestobject. - Execute the
ToDataSourceResult()extension method on the GridDatacollection. You will need to import theTelerik.DataSource.Extensionsnamespace. - The currently visible Grid data will be in the
Dataproperty of theDataSourceResultobject, which is returned byToDataSourceResult(). The total Grid item count (on all pages) will be in theTotalproperty.
The most important part of the example below is in the RequestCurrentMainGridData() method.
Get current filtered and sorted Grid data when using Data parameter
@using Telerik.DataSource
@using Telerik.DataSource.Extensions
<TelerikButton OnClick="@GetCurrentMainGridData">Get Main Grid Data</TelerikButton>
or
<label>
<TelerikCheckBox @bind-Value="@ShouldUseOnStateChanged" />
Detect Main Grid Changes Automatically
</label>
<h2>Main Grid</h2>
<TelerikGrid @ref="@GridRef"
Data="@GridData"
TItem="@Product"
Pageable="true"
PageSize="@GridPageSize"
Sortable="true"
FilterMode="GridFilterMode.FilterRow"
Groupable="true"
OnStateChanged="@OnGridStateChanged">
<GridToolBarTemplate>
<GridSearchBox />
</GridToolBarTemplate>
<GridColumns>
<GridColumn Field="@nameof(Product.Name)" />
<GridColumn Field="@nameof(Product.Stock)" />
<GridColumn Field="@nameof(Product.ReleaseDate)" Title="Release Date" />
<GridColumn Field="@nameof(Product.InProduction)" />
</GridColumns>
</TelerikGrid>
<h2>Current Page in Main Grid</h2>
<p>Showing @( Math.Min(GridPageSize, CurrentMainGridTotal) ) item(s) out of @CurrentMainGridTotal.</p>
<TelerikGrid Data="@CurrentMainGridData">
<GridColumns>
<GridColumn Field="@nameof(Product.Name)" />
<GridColumn Field="@nameof(Product.Stock)" />
<GridColumn Field="@nameof(Product.ReleaseDate)" Title="Release Date" />
<GridColumn Field="@nameof(Product.InProduction)" />
</GridColumns>
</TelerikGrid>
@code {
private TelerikGrid<Product> GridRef { get; set; } = null!;
private List<Product> GridData { get; set; } = new List<Product>();
private List<Product> CurrentMainGridData { get; set; } = new List<Product>();
private int CurrentMainGridTotal { get; set; }
private int GridPageSize { get; set; } = 4;
private bool ShouldUseOnStateChanged { get; set; } = true;
private void OnGridStateChanged(GridStateEventArgs<Product> args)
{
if (ShouldUseOnStateChanged)
{
RequestCurrentMainGridData(args.GridState);
}
}
private void GetCurrentMainGridData()
{
RequestCurrentMainGridData(GridRef.GetState());
}
private void RequestCurrentMainGridData(GridState<Product> gridState)
{
var filterAndSearchDescriptors = new List<IFilterDescriptor>(gridState.FilterDescriptors);
filterAndSearchDescriptors.Add(gridState.SearchFilter);
var request = new DataSourceRequest()
{
Filters = filterAndSearchDescriptors,
Groups = gridState.GroupDescriptors.ToList(),
Page = gridState.Page ?? 1, // for paging
PageSize = GridPageSize,
Skip = gridState.Skip ?? 0, // for virtual scrolling
Sorts = gridState.SortDescriptors.ToList()
};
var result = GridData.ToDataSourceResult(request);
if (gridState.GroupDescriptors.Any())
{
var groups = result.Data.Cast<AggregateFunctionsGroup>();
CurrentMainGridData = new List<Product>();
foreach (var group in groups)
{
CurrentMainGridData.AddRange(group.Items.Cast<Product>().ToList());
}
}
else
{
CurrentMainGridData = result.Data.Cast<Product>().ToList();
}
CurrentMainGridTotal = result.Total;
}
protected override void OnInitialized()
{
var rnd = new Random();
for (int i = 1; i <= 30; i++)
{
GridData.Add(new Product()
{
Id = i,
Name = $"Product {i}",
Price = (decimal)rnd.Next(1, 100),
Stock = rnd.Next(0, 50),
ReleaseDate = DateTime.Now.AddDays(-rnd.Next(60, 1000)),
InProduction = i % 4 == 0
});
}
CurrentMainGridData = GridData.Take(GridPageSize).ToList();
CurrentMainGridTotal = GridData.Count;
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public decimal Price { get; set; }
public int Stock { get; set; }
public DateTime ReleaseDate { get; set; }
public bool InProduction { get; set; }
}
}
When Using OnRead Event
- Implement the Grid
OnReadevent handler as usual. More Grid-specific examples are available in the Grid Manual Operations article. - The visible data items on the current Grid page are in the
args.Datacollection, which is set in the GridOnReadhandler.args.Datais a property of theGridReadEventArgsevent argument, so it's not accessible outsideOnRead. That's why you can cache it in a separate variable, together with the total item count (args.Total).
Optionally, if you want to get the currently filtered and sorted data from all Grid pages:
- Execute
ToDataSourceResult()over the Grid datasource as usual. This will produce the data items on the current Grid page. - Reset the
Page,PageSize, andSkipproperties of theDataSourceRequestobject in theGridReadEventArgsevent argument. - Repeat the
ToDataSourceResult()call over the Grid datasource. This will produce the data items from all Grid pages.
The most important part of the example below is in the OnGridRead handler.
Get current filtered and sorted Grid data when using OnRead event
@using Telerik.DataSource
@using Telerik.DataSource.Extensions
<h2>Main Grid</h2>
<TelerikGrid OnRead="@OnGridRead"
TItem="@Product"
Pageable="true"
PageSize="@GridPageSize"
Sortable="true"
FilterMode="GridFilterMode.FilterRow"
Groupable="true">
<GridToolBarTemplate>
<GridSearchBox />
</GridToolBarTemplate>
<GridColumns>
<GridColumn Field="@nameof(Product.Name)" />
<GridColumn Field="@nameof(Product.Stock)" />
<GridColumn Field="@nameof(Product.ReleaseDate)" Title="Release Date" />
<GridColumn Field="@nameof(Product.InProduction)" />
</GridColumns>
</TelerikGrid>
<h2>Current Page in Main Grid</h2>
<p>Showing @( Math.Min(GridPageSize, CurrentMainGridTotal) ) item(s) out of @CurrentMainGridTotal.</p>
<TelerikGrid Data="@CurrentMainGridData">
<GridColumns>
<GridColumn Field="@nameof(Product.Name)" />
<GridColumn Field="@nameof(Product.Stock)" />
<GridColumn Field="@nameof(Product.ReleaseDate)" Title="Release Date" />
<GridColumn Field="@nameof(Product.InProduction)" />
</GridColumns>
</TelerikGrid>
@code {
private List<Product> GridData { get; set; } = new List<Product>();
private List<Product> CurrentMainGridData { get; set; } = new List<Product>();
private int CurrentMainGridTotal { get; set; }
private int GridPageSize { get; set; } = 4;
private async Task OnGridRead(GridReadEventArgs args)
{
DataSourceResult result = GridData.ToDataSourceResult(args.Request);
args.Data = result.Data;
args.Total = CurrentMainGridTotal = result.Total;
if (args.Request.Groups.Any())
{
var groups = result.Data.Cast<AggregateFunctionsGroup>();
CurrentMainGridData = new List<Product>();
foreach (var group in groups)
{
CurrentMainGridData.AddRange(group.Items.Cast<Product>().ToList());
}
}
else
{
CurrentMainGridData = result.Data.Cast<Product>().ToList();
}
}
protected override void OnInitialized()
{
var rnd = new Random();
for (int i = 1; i <= 30; i++)
{
GridData.Add(new Product()
{
Id = i,
Name = $"Product {i}",
Price = (decimal)rnd.Next(1, 100),
Stock = rnd.Next(0, 50),
ReleaseDate = DateTime.Now.AddDays(-rnd.Next(60, 1000)),
InProduction = i % 4 == 0
});
}
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public decimal Price { get; set; }
public int Stock { get; set; }
public DateTime ReleaseDate { get; set; }
public bool InProduction { get; set; }
}
}