The scenario is:
In this case, the Grid should not try to create or clone an edit item on its own. Instead, it should rely on the returned instance from OnModelInit. However, the Grid first fires OnModelInit and then it still tries to clone or create an edit item, which causes an exception.
A possible workaround is to manage the whole edit process manually, similar to the example with ListView popup editing.
I have a Grid with row selection and column virtualization. After selecting all rows and zooming out my browser to 80% or less, the column virtualization stops working - data is not loaded in the cells on vertical scroll.
I use a custom filter row for the Grid where I have added a custom component holding the filter cell content. I am saving the Grid state upon change and restoring it on initialization.
I noticed that the custom filter component is initialized before the Grid state. As a result, there is an applied filter but the input in the custom filter component does not show it.
This behaviour was new since version 6.0.0. With 5.1.1 it doesn't appear.
I have a grid that can have a large number of pages and is intended to be able to be viewed on a small width device.
The issue is that upon loading the grid and its data, the pager of the grid isn't changing how it's displayed even though it is supposed to be adaptive.
If the page is manually resized, only then does the pager correctly show as a dropdown.
I've reproduced this in a REPL, though it seems slightly inconsistent as opposed to my main project where it is able to be reproduced every time.
In the attached gif, notice that upon loading the page, the grid shows the pager as a list of numbers as it would if the page was a large width screen, but when resizing the page slightly, it is triggered to show the pages as a dropdown, which I believe is the intended behavior.
Is this issue known and is there a way to trigger the grid to redraw its pager after the data is loaded, or some other form of workaround for this without implementing a custom pager template?
Please consider adding built-in support for a TextTruncationWithAction or TruncateWithButton mode on GridColumn components. This feature would display long text as truncated with ellipsis (...) and a button or icon to reveal the full content, such as in a modal or popover.
Why This Is Needed
In enterprise applications like ERP, cutover planning, or audit logs, we often display descriptions, notes, or comments that can span multiple lines. However:
Please consider extending the GridColumn component to include fine-grained header presentation properties, such as:
These enhancements would dramatically improve clarity and usability in complex data grids.
Why This Is Important
In enterprise-grade applications — like ERP dashboards, financial reporting, or cutover schedules — grids are dense and loaded with meaning. Users rely heavily on headers to interpret the data beneath, especially when:
Please consider adding new grid-level properties to control visual styling and editing behavior more intuitively:
These options would provide teams with greater flexibility to align grids with branding, accessibility, and user interaction standards.
Why This Is Valuable
Grids are the centerpiece of most enterprise applications — and users rely on visual consistency and responsive interaction. Today’s grids need to:
These settings would empower developers to deliver purpose-built grids without deep CSS overrides or workarounds.
I discovered "incell" editing mode on the grid, I love it! It makes the UI very intuitive and quick to update individual fields. It also works great with a PATCH API endpoint.
One minor glitch with "incell editing". If I click on a cell in a different row, it immediately takes the previous cell out of edit and puts the new cell in edit with a single click -- VERY cool. But, if you click on a cell in the same row it takes the previous cell out of edit, but doesn't put the new cell in edit mode. It would be cool if it worked the same as the "clicking in separate rows" functionality.
Thanks,
Kenny
Consider the following scenario:
<TelerikGrid Data="Animals" Sortable="true">
<TelerikGridColumns>
<TelerikGridColumn Field="Color"></TelerikGridColumn>
<TelerikGridColumn Field="Breed"></TelerikGridColumn>
</TelerikGridColumns>
</TelerikGrid>
@functions {
public List<Animal> Animals { get; set; } = new List<Animal> { new Dog { Breed = "Sheepdog", Color = "Black" } };
public class Animal { public string Color { get; set; } }
public class Dog : Animal { public string Breed { get; set; } }
}
Everything renders fine for the grid until you attempt to sort by Breed, which results in the following exception:
System.ArgumentException: Invalid property or field - 'Breed' for type: Animal
Not sure what is going on under the hood here, but perhaps this could be fixed by looking at the type of the object, rather than the underlying list? I'm aware that this can be fixed by changing the data source to List<Dog> , but I think this use case of using a base-class is useful for many dynamic scenarios (think dynamic columns, etc)
Repro steps:
Actual: The "Name" field is blank
Expected: All fields have the appropriate data
Reproducible below, expected results is that after editing the decimal field you'll get the data under the grid. Actual: either it does not get updated, or the value is always 0.
@
using
Telerik.Blazor.Components.Grid
<TelerikGrid Data=@MyData EditMode=
"incell"
Pageable=
"true"
Height=
"500px"
>
<TelerikGridEvents>
<EventsManager OnUpdate=
"@UpdateHandler"
OnEdit=
"@EditHandler"
OnDelete=
"@DeleteHandler"
OnCreate=
"@CreateHandler"
></EventsManager>
</TelerikGridEvents>
<TelerikGridToolBar>
<TelerikGridCommandButton Command=
"Add"
Icon=
"add"
>Add Employee</TelerikGridCommandButton>
</TelerikGridToolBar>
<TelerikGridColumns>
<TelerikGridColumn Field=@nameof(SampleData.ID) Title=
"ID"
Editable=
"false"
/>
<TelerikGridColumn Field=@nameof(SampleData.Name) Title=
"Name"
/>
<TelerikGridColumn Field=@nameof(SampleData.SomeDecimal) Title=
"Some Decimal"
/>
<TelerikGridCommandColumn>
<TelerikGridCommandButton Command=
"Delete"
Icon=
"delete"
>Delete</TelerikGridCommandButton>
<TelerikGridCommandButton Command=
"Save"
Icon=
"save"
ShowInEdit=
"true"
>Update</TelerikGridCommandButton>
</TelerikGridCommandColumn>
</TelerikGridColumns>
</TelerikGrid>
@lastUpdateOnDecimal
@code {
public
void
EditHandler(GridCommandEventArgs args)
{
SampleData item = (SampleData)args.Item;
Console.WriteLine(
"Edit event is fired for column "
+ args.Field);
}
string
lastUpdateOnDecimal;
public
void
UpdateHandler(GridCommandEventArgs args)
{
string
fieldName = args.Field;
object
newVal = args.Value;
//you can cast this, if necessary, according to your model
SampleData item = (SampleData)args.Item;
//you can also use the entire model
//perform actual data source operation here
//if you have a context added through an @inject statement, you could call its SaveChanges() method
//myContext.SaveChanges();
if
(fieldName ==
"SomeDecimal"
)
{
lastUpdateOnDecimal = $
"decimal for {item.ID} updated to {newVal} on {DateTime.Now}"
;
}
var matchingItem = MyData.FirstOrDefault(c => c.ID == item.ID);
if
(matchingItem !=
null
)
{
matchingItem.Name = item.Name;
}
Console.WriteLine(
"Update event is fired for "
+ args.Field +
" with value "
+ args.Value);
}
public
void
CreateHandler(GridCommandEventArgs args)
{
SampleData item = (SampleData)args.Item;
//perform actual data source operation here
item.ID = MyData.Count;
MyData.Add(item);
Console.WriteLine(
"Create event is fired."
);
}
public
void
DeleteHandler(GridCommandEventArgs args)
{
SampleData item = (SampleData)args.Item;
//perform actual data source operation here
//if you have a context added through an @inject statement, you could call its SaveChanges() method
//myContext.SaveChanges();
MyData.Remove(item);
Console.WriteLine(
"Delete event is fired."
);
}
//in a real case, keep the models in dedicated locations, this is just an easy to copy and see example
public
class
SampleData
{
public
int
ID {
get
;
set
; }
public
string
Name {
get
;
set
; }
public
decimal
SomeDecimal {
get
;
set
; }
}
public
List<SampleData> MyData {
get
;
set
; }
protected
override
void
OnInit()
{
MyData =
new
List<SampleData>();
for
(
int
i = 0; i < 50; i++)
{
MyData.Add(
new
SampleData()
{
ID = i,
Name =
"Name "
+ i.ToString(),
SomeDecimal = i
});
}
}
}
Reproducible
@using Telerik.Blazor
@using Telerik.Blazor.Components.Grid
<TelerikGrid Data=@GridData
SelectionMode="GridSelectionMode.Multiple"
@bind-SelectedItems="SelectedItems"
Pageable="true"
Height="400px">
<TelerikGridToolBar>
<TelerikGridCommandButton Command="MyDelete" OnClick="DeleteSelectedAsync"
Enabled=@(SelectedItems?.Count() > 0) Icon="delete">Delete</TelerikGridCommandButton>
<TelerikGridCommandButton Enabled="false" OnClick="DeleteSelectedAsync">I must always be disabled</TelerikGridCommandButton>
</TelerikGridToolBar>
<TelerikGridColumns>
<TelerikGridCheckboxColumn />
<TelerikGridColumn Field=@nameof(Employee.Name) />
<TelerikGridColumn Field=@nameof(Employee.Team) Title="Team" />
</TelerikGridColumns>
</TelerikGrid>
@result
@if (SelectedItems != null)
{
<ul>
@foreach (Employee employee in SelectedItems)
{
<li>
@employee.Name
</li>
}
</ul>
}
@code {
void DeleteSelectedAsync()
{
result = $"On {DateTime.Now} there are {SelectedItems?.Count()} items selected";
}
string result;
public List<Employee> GridData { get; set; }
public IEnumerable<Employee> SelectedItems { 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
});
}
// select Employee with 3 through 5
SelectedItems = GridData.Skip(2).Take(3).ToList();
}
public class Employee
{
public int EmployeeId { get; set; }
public string Name { get; set; }
public string Team { get; set; }
}
}
You can work around this by disabling virtual scrolling with something like this:
ScrollMode="@(Data.Count() > 30 ? GridScrollMode.Virtual : GridScrollMode.Scrollable)"
Simplest repro code is below - expand a few rows and select items in them, or in the parent grid. I would expect that selection in each grid is independent, but the child grid seems to control the parent selection too, even though it is disabled.
<TelerikGrid Data="salesTeamMembers" PageSize="4" Pageable="true" @bind-SelectedItems="@SelectedItemsMainGrid" SelectionMode="@GridSelectionMode.Single">
<DetailTemplate>
@{
var employee = context as MainModel;
<TelerikGrid Data="employee.Orders" Pageable="true" PageSize="7" SelectionMode="@GridSelectionMode.None">
<GridColumns>
<GridColumn Field="OrderId"></GridColumn>
<GridColumn Field="DealSize"></GridColumn>
</GridColumns>
</TelerikGrid>
}
</DetailTemplate>
<GridColumns>
<GridColumn Field="Id"></GridColumn>
<GridColumn Field="Name"></GridColumn>
</GridColumns>
</TelerikGrid>
@foreach (var item in SelectedItemsMainGrid)
{
<div>@item.Name</div>
}
@code {
List<MainModel> salesTeamMembers { get; set; }
public IEnumerable<MainModel> SelectedItemsMainGrid { get; set; } = Enumerable.Empty<MainModel>();
protected override void OnInitialized()
{
salesTeamMembers = GenerateData();
}
private List<MainModel> GenerateData()
{
List<MainModel> data = new List<MainModel>();
for (int i = 1; i < 16; i++)
{
MainModel mdl = new MainModel { Id = i, Name = $"Name {i}" };
mdl.Orders = Enumerable.Range(1, 15).Select(x => new DetailsModel { OrderId = x, DealSize = x ^ i }).ToList();
data.Add(mdl);
}
return data;
}
public class MainModel
{
public int Id { get; set; }
public string Name { get; set; }
public List<DetailsModel> Orders { get; set; }
}
public class DetailsModel
{
public int OrderId { get; set; }
public double DealSize { get; set; }
}
}
I would like to be able to edit both Date and Time in Grid editing mode.
===
Telerik edit: Possible since version 3.1.0 with through the column EditorType parameter.