Regression introduced in version 10.0.0.
The OnStateChanged event fires 4 times
The OnStateChanged event fires 2 times (see https://www.telerik.com/blazor-ui/documentation/components/grid/state#onstatechanged).
All
9.1.0
Please add support for programmatic exporting of Grids (SaveAsExcelFileAsync() and ExportToExcelAsync() ) with a GridExcelExportOptions argument and multi-column headers.
===
A potential workaround is to programmatically click the built-in export command button, which can even be hidden:
@using Telerik.Blazor.Components.Grid
@inject IJSRuntime JS
<PageTitle>Home</PageTitle>
<TelerikGrid Data="@GridData">
<GridToolBarTemplate>
<TelerikButton OnClick="@ExportGridWithOtherColumns">Export Programmatically</TelerikButton>
<GridCommandButton Class="hidden-export-button" Command="ExcelExport">Export Natively</GridCommandButton>
</GridToolBarTemplate>
<GridSettings>
<GridExcelExport OnBeforeExport="@OnGridBeforeExport" />
</GridSettings>
<GridColumns>
<GridColumn Field="@nameof(Product.Id)" Width="100px" />
<GridColumn Field="@nameof(Product.Name)" Width="120px" />
<GridColumn Title="Product Details">
<Columns>
<GridColumn Field="@nameof(Product.Group)" Width="180px" />
<GridColumn Field="@nameof(Product.Price)" DisplayFormat="{0:c2}" Width="120px" />
<GridColumn Field="@nameof(Product.Quantity)" DisplayFormat="{0:n0}" Width="120px" />
<GridColumn Field="@nameof(Product.Released)" DisplayFormat="{0:d}" Width="180px" />
<GridColumn Field="@nameof(Product.Discontinued)" Width="100px" />
</Columns>
</GridColumn>
</GridColumns>
</TelerikGrid>
<style>
.hidden-export-button {
display: none;
}
</style>
<script suppress-error="BL9992">
function clickExportCommandButton() {
let hiddenExportButton = document.querySelector(".hidden-export-button");
if (hiddenExportButton) {
hiddenExportButton.click();
}
}
</script>
@code {
private List<Product> GridData { get; set; } = new();
private void OnGridBeforeExport(GridBeforeExcelExportEventArgs args)
{
List<string> exportableColumnFields = new List<string> { nameof(Product.Name), nameof(Product.Price), nameof(Product.Quantity) };
List<GridExcelExportColumn> ColumnsToExport = new();
foreach (GridExcelExportColumn column in args.Columns)
{
if (exportableColumnFields.Contains(column.Field))
{
ColumnsToExport.Add(column);
}
}
args.Columns = ColumnsToExport;
}
private async Task ExportGridWithOtherColumns()
{
await JS.InvokeVoidAsync("clickExportCommandButton");
}
protected override void OnInitialized()
{
var rnd = Random.Shared;
for (int i = 1; i <= 7; i++)
{
GridData.Add(new Product()
{
Id = i,
Name = $"Name {i} {(char)rnd.Next(65, 91)}{(char)rnd.Next(65, 91)}",
Group = $"Group {i % 3 + 1}",
Price = rnd.Next(1, 100) * 1.23m,
Quantity = rnd.Next(0, 10000),
Released = DateTime.Today.AddDays(-rnd.Next(60, 1000)),
Discontinued = i % 4 == 0
});
}
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Group { get; set; } = string.Empty;
public decimal Price { get; set; }
public int Quantity { get; set; }
public DateTime Released { get; set; }
public bool Discontinued { get; set; }
}
}
Workaround:
<TelerikGrid Data="@GridData"
SelectionMode="@GridSelectionMode.Multiple"
SelectedItems="@SelectedItems"
SelectedItemsChanged="@( (IEnumerable<Employee> newSelected) => OnSelectedItemsChanged(newSelected) )"
Height="300px">
<GridToolBarTemplate>
<TelerikButton Enabled="@(SelectedItems.Any())" OnClick="@DeleteSelectedEmployees">Delete</TelerikButton>
</GridToolBarTemplate>
<GridColumns>
<GridCheckboxColumn SelectAll="true" />
<GridColumn Field="Name" Title="Name" />
<GridColumn Field="Team" Title="Team" />
</GridColumns>
</TelerikGrid>
@code {
private List<Employee> GridData { get; set; } = Enumerable.Range(1, 10).Select(i => new Employee
{
EmployeeId = i,
Name = $"Employee {i}",
Team = $"Team {i % 3}"
}).ToList();
private List<Employee> SelectedItems { get; set; } = new();
private void OnSelectedItemsChanged(IEnumerable<Employee> items)
{
SelectedItems = items.ToList();
}
private void DeleteSelectedEmployees()
{
if (SelectedItems.Any())
{
GridData = GridData.Except(SelectedItems).ToList();
SelectedItems.Clear();
}
}
public class Employee
{
public int EmployeeId { get; set; }
public string Name { get; set; }
public string Team { get; set; }
public override bool Equals(object obj) => obj is Employee e && e.EmployeeId == EmployeeId;
public override int GetHashCode() => EmployeeId.GetHashCode();
}
}
I'm using an OnRead grid with ExpandoObjects. The error happens on the backend when trying to process the result of ToDataSourceResult(...)
When trying to access the Items property of AggregateFunctionsGroup in a multi level grouping scenario, using ExpandoObject, and the top level group has a null key, trying to access the Items property will result in a NullReferenceException. I've made this helper, but it cannot process the subgroups because of this error.
private static void FlattenGroup<T>(AggregateFunctionsGroup group, List<T> result)
{
if (group == null)
{
return;
}
if (group.HasSubgroups)
{
foreach (var sub in group.Items.OfType<AggregateFunctionsGroup>())
{
FlattenGroup(sub, result);
}
}
else
{
result.AddRange(group.Items.OfType<T>());
}
}In a scenario where I have an ExpandoObject with properties A and B, where A = 1 and B = null; grouping by A then B works. Grouping by A or B alone also works. But grouping by B then A causes the NullReferenceException when trying to access the group.Items.
When Virtual Scrolling is enabled and the grid is set to inline editing, clicking the Add button does not start editing on the first click. The button must be clicked twice for a new row to enter edit mode.
Steps to Reproduce:
1. Open this example - https://blazorrepl.telerik.com/QfaZEibY50abpby200
2. Scroll down the grid.
3. Click the "Add" button.
Upon the first click, a new row is inserted but then immediately closed. You have to click it a second time to insert a new row.
Similar to the WPF grid I would like the option to require the user hold shift to sort by multiple columns, otherwise the grid would sort by only a single column.
https://docs.telerik.com/devtools/wpf/controls/radgridview/sorting/multiple-column-sorting
Hy,
It is possible to have default color themes (Primary,Dark,Info,Error,...) for Telerik Blazor Grid component as well without having to change the color by css overriding?
The issue targets a Grid with cell selection and DragToSelect feature disabled where at least one column has Visible="false". With this configuration, when using Shift + Click to select multiple cells, the result is a mismatch in the cells that should be selected, after the position where the invisible column is placed.
Video reproduction attached. Reproduction code: https://blazorrepl.telerik.com/GyFuQwPf37H8riAM19.
After filtering a nullable int column, the SelectAll checkbox in the GridCheckboxColumn stops working.
Reproduction example: https://blazorrepl.telerik.com/mTuyHaYM44sLH2yf05
The focus indicator on the GridSearchBox is broken when using an outline themes like A11Y, Bootstrap etc.
Temporarily override the overflow style on .k-toolbar-items (e.g., overflow: unset;) using custom CSS to restore the focus indicator.
Grid OnRead .Clear() Issue
With the following component:
@page "/counter"
@using System.Collections.ObjectModel
General grid with its most common features
<TelerikGrid Data="@MyData" Pageable="true" @bind-Page="page" PageSize="5" TotalCount="30" OnRead="@ReadItems" >
<GridColumns>
<GridColumn Field="@(nameof(SampleData.Id))" Width="120px" />
<GridColumn Field="@(nameof(SampleData.Name))" Title="Employee Name" Groupable="false" />
<GridColumn Field="@(nameof(SampleData.Team))" Title="Team" />
<GridColumn Field="@(nameof(SampleData.HireDate))" Title="Hire Date" />
</GridColumns>
</TelerikGrid>
@code {
public List<SampleData> MyData { get; set; } = new List<SampleData>();
//public ObservableCollection<SampleData> MyData { get; set; } = new ObservableCollection<SampleData>();
private int page = 1;
private void ReadItems(GridReadEventArgs args)
{
//MyData = new List<SampleData>(); //OK!
//MyData = new ObservableCollection<SampleData>(); //OK!
MyData.Clear(); //List: No update. ObservableCollection: System.StackOverflowException!
Populate();
StateHasChanged();
}
private void Populate()
{
foreach (var data in Enumerable.Range((page - 1) * 5, 5).Select(x => new SampleData
{
Id = x,
Name = "name " + x,
Team = "team " + x % 5,
HireDate = DateTime.Now.AddDays(-x).Date
}))
{
MyData.Add(data);
}
}
public class SampleData
{
public int Id { get; set; }
public string Name { get; set; }
public string Team { get; set; }
public DateTime HireDate { get; set; }
}
}I see the issues in the comment fields. Changing OnRead to async makes no difference.
The workaround is to assign a new List or ObservableCollection instead of using .Clear()
Refreshing the Grid data frequently may cause performance issues.