There is an undocumented breaking change in the selection behavior of the v13.0.0 TreeView component that prevents us from upgrading from v12.3.0.
In v12.3.0, selecting a TreeView checkbox does change the TreeView item selection or trigger the selection change events. In v13.0.0, checking an item does also change the selection. The v12.3.0 behavior is important for our implementation because selecting a TreeView item in our application fetches data from a database and we do not want the performance overhead of those calls when checking an item---we want the user to be able to select multiple items and only then explicitly fetch the data for all of them.
I've created a minimal example here: https://blazorrepl.telerik.com/cqYdEePd40Zq3ava43. You can see the behavior differences when switching between versions.
Please let me know if there's any additional information we can provide. A workaround to this behavior would be appreciated. Thank you!
The Font Size and Font Family tools display the currently applied style value in the user selection only if the selection is inside one HTML element. This prevents the user from resetting (removing) the current font style.
Test scenario:
@using Telerik.Blazor.Components.Editor
<TelerikEditor @bind-Value="@EditorValue"
Tools="@EditorToolSets.All" />
<h2>Raw Editor Value</h2>
<TelerikTextArea @bind-Value="@EditorValue"
Rows="5" />
@code {
private string EditorValue { get; set; } = @"<p><strong>Foo</strong> foo foo.</p><p>Bar <strong>bar</strong> bar.</p><p>Baz baz <strong>baz</strong>.</p>";
}The possible workarounds are:
How to reproduce:
The regression was introduced in version 12.2.0. The last version that works correctly is 12.0.0.
The possible workarounds are:
@using System.ComponentModel.DataAnnotations
@using Telerik.DataSource
@using Telerik.DataSource.Extensions
<TelerikGrid @ref="@GridRef"
OnRead="@OnGridRead"
TItem="@Product"
EditMode="@GridEditMode.Incell"
OnCreate="@OnGridCreate"
OnDelete="@OnGridDelete"
OnUpdate="@OnGridUpdate"
Height="600px">
<GridToolBarTemplate>
<GridCommandButton Command="Add">Add Item</GridCommandButton>
</GridToolBarTemplate>
<GridColumns>
<GridColumn Field="@nameof(Product.Name)">
<EditorTemplate>
@{ var dataItem = (Product)context; }
<span @onfocusout="@( async () => await OnGridCellFocusOut(nameof(Product.Name)) )">
<TelerikTextBox @bind-Value="@dataItem.Name" />
</span>
</EditorTemplate>
</GridColumn>
@* <GridColumn Field="@nameof(Product.Price)" DisplayFormat="{0:C2}" />
<GridColumn Field="@nameof(Product.Quantity)" DisplayFormat="{0:N0}" />
<GridColumn Field="@nameof(Product.ReleaseDate)" DisplayFormat="{0:d}" /> *@
<GridColumn Field="@nameof(Product.Discontinued)" Width="120px">
<EditorTemplate>
@{ var dataItem = (Product)context; }
<span @onfocusout="@( async () => await OnGridCellFocusOut(nameof(Product.Discontinued)) )">
<TelerikCheckBox @bind-Value="@dataItem.Discontinued" />
</span>
</EditorTemplate>
</GridColumn>
<GridCommandColumn Width="180px">
<GridCommandButton Command="Delete">Delete</GridCommandButton>
</GridCommandColumn>
</GridColumns>
</TelerikGrid>
@code {
private TelerikGrid<Product>? GridRef { get; set; }
private ProductService GridProductService { get; set; } = new();
private async Task OnGridCellFocusOut(string field)
{
await Task.Delay(100);
if (GridRef is null)
{
return;
}
GridState<Product> gridState = GridRef.GetState();
Product? editItem = gridState.EditItem as Product;
if (editItem is null)
{
return;
}
GridCommandEventArgs args = new GridCommandEventArgs()
{
Field = field,
Item = editItem
};
await OnGridUpdate(args);
gridState.EditField = default;
gridState.EditItem = default!;
gridState.OriginalEditItem = default!;
await GridRef.SetStateAsync(gridState);
}
private async Task OnGridCreate(GridCommandEventArgs args)
{
var createdItem = (Product)args.Item;
await GridProductService.Create(createdItem);
}
private async Task OnGridDelete(GridCommandEventArgs args)
{
var deletedItem = (Product)args.Item;
await GridProductService.Delete(deletedItem);
}
private async Task OnGridRead(GridReadEventArgs args)
{
DataSourceResult result = await GridProductService.Read(args.Request);
args.Data = result.Data;
args.Total = result.Total;
args.AggregateResults = result.AggregateResults;
}
private async Task OnGridUpdate(GridCommandEventArgs args)
{
var updatedItem = (Product)args.Item;
await GridProductService.Update(updatedItem);
}
public class Product
{
public int Id { get; set; }
[Required]
public string Name { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public decimal? Price { get; set; }
public int Quantity { get; set; }
[Required]
public DateTime? ReleaseDate { get; set; }
public bool Discontinued { get; set; }
}
#region Data Service
public class ProductService
{
private List<Product> Items { get; set; } = new();
private int LastId { get; set; }
public async Task<int> Create(Product product)
{
await SimulateAsyncOperation();
product.Id = ++LastId;
Items.Insert(0, product);
return LastId;
}
public async Task<bool> Delete(Product product)
{
await SimulateAsyncOperation();
if (Items.Contains(product))
{
Items.Remove(product);
return true;
}
return false;
}
public async Task<List<Product>> Read()
{
await SimulateAsyncOperation();
return Items;
}
public async Task<DataSourceResult> Read(DataSourceRequest request)
{
return await Items.ToDataSourceResultAsync(request);
}
public async Task<bool> Update(Product product)
{
await SimulateAsyncOperation();
int originalItemIndex = Items.FindIndex(x => x.Id == product.Id);
if (originalItemIndex != -1)
{
Items[originalItemIndex] = product;
return true;
}
return false;
}
private async Task SimulateAsyncOperation()
{
await Task.Delay(100);
}
public ProductService(int itemCount = 5)
{
Random rnd = Random.Shared;
for (int i = 1; i <= itemCount; i++)
{
Items.Add(new Product()
{
Id = ++LastId,
Name = $"Product {LastId}",
Description = $"Multi-line\ndescription {LastId}",
Price = LastId % 2 == 0 ? null : rnd.Next(0, 100) * 1.23m,
Quantity = LastId % 2 == 0 ? 0 : rnd.Next(0, 3000),
ReleaseDate = DateTime.Today.AddDays(-rnd.Next(365, 3650)),
Discontinued = LastId % 2 == 0
});
}
}
}
#endregion Data Service
}
The following exception occurs:
Microsoft.JSInterop.JSDisconnectedException: JavaScript interop calls cannot be issued at this time. This is because the circuit has disconnected and is being disposed.
............
at Telerik.Blazor.Components.Common.Loader.ComponentLoaderContainer.DisposeAsync()
When the user closes the browser and the web page contains any of the below components:
When the user selects a value and then focuses on another component the OnBlur of the ComboBox is not triggered. The issue is reproducible in the Firefox browser (tested with version 109.0).
To reproduce the issue open the following REPL example in the Firefox browser:
https://blazorrepl.telerik.com/mdklmHYN06lVQjyL26
Select a value in the first ComboBox and then focus on the second ComboBox. The OnBlur event should trigger.
Hi Telerik Support
Facing an issue with Keyboard navigation in Telerik Grid component.
When we use TAB to navigate, the grid header gets focus only for the first time. After completing one round of navigation, second time after the Toolbar buttons, if we TAB out, focus goes to the pager sections skipping the grid header part.
Pls refer the REPL sample from Telerik website:
Steps to reproduce:
1) Use ALT + W and then use TAB key to navigate
2) First focus goes to the Toolbar button (Add Product), then goes to the Grid Header and then if we TAB again focus goes to the Pager section
3) After the Pager section, if we do steps 1 and 2 again, we can see that it skips the Grid Header focus second time onwards.
I would like to add some custom actions into the popup window. I know I can implement a custom edit popup with an entirely custom content and actions. However, this requires a lot of custom work to just add one additional action in the popup. Please provide an easier option to add custom actions in the edit window.
It will be nice to have boundary detection for animation container
We'd like to track the community demand for using the Telerik Blazor components as Custom Elements.
Please share example common scenarios for such usage and list the components you want to register as Custom Elements to use in other SPA frameworks such as Angular or React.
Hi Team,
I would like to request the UI for Blazor Cards to have data-binding functionality.
Thank you!
Hi Telerik team,
In a Blazor Grid with filters enabled the event "OnStateChanged" is fired twice when I use a filter (set, change, remove).
---
ADMIN EDIT
This behavior is expected - when the grid is filtered, there are two actions that happen:
This is not something we intend to change at this point.
---
To reproduce this I took one of the provided examples and added the event handler:
@page "/"
<TelerikGrid Data=@GridData
SelectionMode="GridSelectionMode.Multiple"
SelectedItemsChanged="@((IEnumerable<Employee> employeeList) => OnSelect(employeeList))"
SelectedItems="@PersistedSelectedItems"
@bind-Page="@CurrentPage"
PageSize="@PageSize"
Pageable="true"
FilterMode="GridFilterMode.FilterRow"
OnStateChanged="@((GridStateEventArgs<Employee> args) => OnStateChangedHandler(args))">
<GridColumns>
<GridCheckboxColumn />
<GridColumn Field=@nameof(Employee.EmployeeId) />
<GridColumn Field=@nameof(Employee.Name) />
<GridColumn Field=@nameof(Employee.Team) />
</GridColumns>
</TelerikGrid>
@if (PersistedSelectedItems != null)
{
<ul>
@foreach (Employee employee in PersistedSelectedItems.OrderBy(e => e.EmployeeId))
{
<li>
@employee.EmployeeId
</li>
}
</ul>
}
@code {
public List<Employee> PersistedSelectedItems { get; set; } = new List<Employee>();
int CurrentPage { get; set; }
int PageSize { get; set; } = 5;
private async void OnStateChangedHandler(GridStateEventArgs<Employee> args)
{
await Task.Delay(5000);
}
protected void OnSelect(IEnumerable<Employee> employees)
{
IEnumerable<Employee> CurrentPageEmployees = GridData.Skip(PageSize * (CurrentPage - 1)).Take(PageSize);
if (employees == null || employees.Count() == 0)
{
//the user de-selected all items with the header checkbox
PersistedSelectedItems = PersistedSelectedItems.Except(CurrentPageEmployees).ToList();
}
else
{
//handle any deselected items
var UnselectedEmployees = CurrentPageEmployees.Except(employees);
PersistedSelectedItems = PersistedSelectedItems.Except(UnselectedEmployees).ToList();
//add any new items if they were not selected already
foreach (var item in employees)
{
if (!PersistedSelectedItems.Contains(item))
{
PersistedSelectedItems.Add(item);
}
}
}
}
//data binding and sample data
public List<Employee> GridData { get; set; }
protected override void OnInitialized()
{
GridData = new List<Employee>();
for (int i = 0; i < 15; i++)
{
GridData.Add(new Employee()
{
EmployeeId = i,
Name = "Employee " + i.ToString(),
Team = "Team " + i % 3
});
}
}
public class Employee
{
public int EmployeeId { get; set; }
public string Name { get; set; }
public string Team { get; set; }
}
}Best regards,
Rayko
A workaround is to initialize the collection of the selected items:
<TelerikButton OnClick="@LoadData">Load Data</TelerikButton>
<TelerikGrid Data=@adminUsers Height="300px" Pageable=true PageSize=10 SelectionMode="@GridSelectionMode.Multiple"
@bind-SelectedItems="SelectedAdminUsers">
<GridColumns>
<GridCheckboxColumn SelectAll="true"></GridCheckboxColumn>
<GridColumn Field=@nameof(User.DisplayName) Title="User Name" />
<GridColumn Field=@nameof(User.Department) Title="Department" />
<GridColumn Field=@nameof(User.Status) Title="Status" />
<GridColumn Field=@nameof(User.EmployeeId) Title="Employee Id" />
</GridColumns>
</TelerikGrid>
@code
{
public IEnumerable<User> SelectedAdminUsers { get; set; } = Enumerable.Empty<User>();
public List<User> adminUsers { get; set; }
void LoadData()
{
adminUsers = Enumerable.Range(1, 200).Select(x => new User
{
EmployeeId = x,
Status = $"status {x}",
Department = $"department {x}",
DisplayName = $"name {x}"
}
).ToList();
}
public class User
{
public string DisplayName { get; set; }
public string Department { get; set; }
public string Status { get; set; }
public int EmployeeId { get; set; }
}
}
Before, the Value from the first item in the Data was populated through @bind-Value to the view model. It no longer is.
In the following snippet, I expect to see "1" in the initial load of the page, but I see "0" - the default value for the integer.
@selectedValue
<TelerikDropDownList Data="@myDdlData" TextField="MyTextField" ValueField="MyValueField" @bind-Value="@selectedValue">
</TelerikDropDownList>
@code {
//in a real case, the model is usually in a separate file
//the model type and value field type must be provided to the dropdpownlist
public class MyDdlModel
{
public int MyValueField { get; set; }
public string MyTextField { get; set; }
}
IEnumerable<MyDdlModel> myDdlData = Enumerable.Range(1, 20).Select(x => new MyDdlModel { MyTextField = "item " + x, MyValueField = x });
int selectedValue { get; set; }
}
URL: https://blazorrepl.telerik.com/QJkQPwlw09eSCmk905?_gl=1%2a1wzzh94%2a_gcl_au%2aODg2NjQ4ODc0LjE3NDMwNjY1NTI.%2a_ga%2aODYwMDgyNjY4LjE3MzI3OTMyMTA.%2a_ga_9JSNBCSF54%2aczE3NDc2MzAyNjkkbzUkZzEkdDE3NDc2MzYwMjYkajE4JGwwJGgwJGRHVjE1OElLdHB0ZXJwc1VOWHNzTWlJTEhVVlVQckU0Ynd3
Screen Readers: NVDA (2024.4.2.35031), JAWS (2025.2504.89), Narrator
Screen reader is announcing as 'Select files button collapsed'.
Refer Attachment:
1. Screen reader is not announcing label and note information for 'Select files' button.png
2. Screen reader is not announcing label and note information for 'Select files' button.mp4
I noticed that when the ReadTimeout property of the FileSelect's FileInfoStream is read, the code seem to block completely.
You will find a Blazor Web App project attached to this ticket showcasing the issue.
When enabling/disabling a form element that is defined in a child component, the element is successfully disabled, however a console error occurs. The error occurs whether the child component makes the update or the parent makes the update through a passed parameter. The error does not occur for form elements defined in the parent. The error does not occur for basic html input elements defined in the child.
Element definition:
<TelerikTextBox
Id="ElementMisc"
AutoComplete="new-password"
@bind-Value="@_searchModel.ElementMisc"
Enabled="!_elementSelectMode"
class="textbox-75"
DebounceDelay="0">
</TelerikTextBox>
Update Code defined in child:
if (results.Data.Count > 1)
{
_elementSelectMode= true;
StateHasChanged();
}
Console Error:
Uncaught (in promise) Error: Assertion failed - heap is currently locked
at mr (blazor.web.js:1:158963)
at Object.beginInvokeDotNetFromJS (blazor.web.js:1:157244)
at w.invokeDotNetMethodAsync (blazor.web.js:1:3978)
at C.invokeMethodAsync (blazor.web.js:1:5486)
at r.invokeMethodAsync (telerik-blazor.js:22:1272553)
at r.onBlur (telerik-blazor.js:22:1463592)
at ye.setOrRemoveAttributeOrProperty (blazor.web.js:1:28630)
at ye.applyAttribute (blazor.web.js:1:27574)
at ye.applyEdits (blazor.web.js:1:24601)
at ye.updateComponent (blazor.web.js:1:23606)
Hello,
we are using the PDFViewer Component.
The zoom function usually works perfectly, both on mobile and desktop.
But there is one exception.
There is one scenario, where our PO got an crash, when he try to use ANY zoom functionality of the component.
He is using:
Hello,
I see this often when running your Product updater, or it may come from within VS 2026 when it prompts to update projects. I had Telerik UI for Blazor 13.2 installed, updated using the product updater and got the prompt for the project updater and now 13.3.0 is active. The problem though is when you add a new version entry in the nuget package sources the older version(s) are not being removed. This breaks the build, it will fail to restore packages, etc.