Completed
Last Updated: 11 Apr 2025 15:26 by ADMIN
Created by: Ken
Comments: 1
Category: Grid
Type: Feature Request
2

Please consider extending the GridColumn component to include fine-grained header presentation properties, such as:

  • HeaderAlignment (e.g., Left, Center, Right)
  • WrapHeaderText (bool)
  • HeaderTooltip or HeaderAdornmentTemplate

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:

 

  • Column headers are long or require abbreviations.
  • Users need contextual guidance without clutter.
  • Alignment improves visual scanning and aesthetics.

 

Declined
Last Updated: 11 Apr 2025 08:26 by ADMIN

Please consider adding new grid-level properties to control visual styling and editing behavior more intuitively:

 

  • HeaderThemeColor
  • ShowGridLines
  • EditModeDisplay (e.g., None, ValueOnly, All, Auto)

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:

 

  • Match branding and accessibility guidelines (dark/light, color accessibility).
  • Visually separate data (e.g., grid lines on for financial reports, off for dashboards).
  • Clearly communicate edit state (inline, batch, or value-only editing).

These settings would empower developers to deliver purpose-built grids without deep CSS overrides or workarounds.


Duplicated
Last Updated: 09 Jul 2025 08:24 by ADMIN
Created by: Alexander
Comments: 0
Category: Grid
Type: Bug Report
2

Refreshing the Grid data frequently may cause performance issues.

Completed
Last Updated: 22 Jul 2025 05:55 by ADMIN
Release 2025 Q3 (Aug)
Created by: Alex
Comments: 0
Category: Grid
Type: Bug Report
2

The focus indicator on the GridSearchBox is broken when using an outline themes like A11Y, Bootstrap etc.

Workaround:

Temporarily override the overflow style on .k-toolbar-items (e.g., overflow: unset;) using custom CSS to restore the focus indicator.

Completed
Last Updated: 05 Aug 2025 10:11 by ADMIN
Release 2025 Q3 (Aug)
Currently, users can cancel editing either by clicking the "Cancel" button, the `X` button in the popup header, or by pressing the Esc key. The expectation is that all three actions should trigger the `OnCancel` event.
Unplanned
Last Updated: 30 Jul 2025 07:58 by Stephan
I want to expand a specific section within the column menu, such as the filter, column chooser, or column position section, when the menu is opened. 
Unplanned
Last Updated: 06 Aug 2025 13:06 by Michael
If you set a given column's Groupable/Sortable/Filterable parameter to false, it will still appear in the toolbar tools list of columns.
Unplanned
Last Updated: 03 Nov 2025 08:45 by Jorge
Created by: Jorge
Comments: 0
Category: Grid
Type: Feature Request
2

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; }
    }
}

Planned
Last Updated: 24 Mar 2026 13:31 by ADMIN
Scheduled for 2026 Q2

How to reproduce:

  1. Go to https://demos.telerik.com/blazor-ui/grid/editing-incell
  2. Go to the last Grid page, which has empty space below the last table row.
  3. Open any Grid cell for editing.
  4. Click on the empty space in the Grid below the last table row.
  5. The Grid does not exit edit mode like it should.

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
}

 

Unplanned
Last Updated: 19 Mar 2026 14:46 by Clifton
Specifically, if the div mentioned in the error does not have tabindex=1, tabbing from the header causes the browser to focus that area, which is not the expected behavior. Ideally, the focus should move to the first cell, as that intermediate area is not user-interactive.

On the other hand, if tabindex=-1 is used, tools like Аxe and Lighthouse report errors. Removing the tabindex attribute altogether still results in errors, and the browser continues to focus that area.

We are actively exploring possible approaches to address this, but at the moment, there is no immediate solution we can apply without side effects.
Completed
Last Updated: 09 Apr 2019 21:00 by ADMIN
Created by: Jeff
Comments: 2
Category: Grid
Type: Feature Request
1
Forgive me if this already exists but I can't seem to find a way to specify column widths for the Grid. If there is a way please include this documentation. If there isn't yet a way to do this then please consider this a request for that functionality. Thanks!
Completed
Last Updated: 23 Feb 2020 09:50 by ADMIN

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

Duplicated
Last Updated: 02 Mar 2020 13:22 by ADMIN
Created by: Shaun
Comments: 2
Category: Grid
Type: Bug Report
1

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
   at Telerik.DataSource.Expressions.MemberAccessTokenExtensions.CreateMemberAccessExpression(IMemberAccessToken token, Expression instance)

 

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)

Declined
Last Updated: 18 Oct 2019 15:39 by ADMIN
    <TelerikGrid Data=@theViewModel.RowItems
                                 TotalCount=@theViewModel.TotalRecordCount
                                 Filterable=false
                                 Sortable=true
                                 Pageable=true
                                 EditMode="inline"
                                 PageSize=@theViewModel.PageSize>
                        <TelerikGridEvents>
                            <EventsManager OnRead=@ReadItems></EventsManager>
                        </TelerikGridEvents>
                        <TelerikGridColumns>
                            <TelerikGridColumn Field=@nameof(EmployeeTodo.Text) Title="Title" />
                            <TelerikGridColumn Field=@nameof(EmployeeTodo.CreationDate) Title="Date" />
                        </TelerikGridColumns>
                    </TelerikGrid>
Completed
Last Updated: 29 Jul 2019 10:36 by ADMIN
Release 1.5.0
Created by: Rick
Comments: 0
Category: Grid
Type: Bug Report
1

Repro steps:

  1. Go to https://demos.telerik.com/blazor-ui/grid/editing-inline
  2. Click Add
  3. Enter some data in all editable fields
  4. Click Update
  5. Go to the last page

Actual: The "Name" field is blank

Expected: All fields have the appropriate data

Completed
Last Updated: 02 Oct 2019 07:20 by ADMIN
Release 1.5.0

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
            });
        }
    }
}

 

Duplicated
Last Updated: 02 Mar 2020 13:26 by ADMIN
Created by: Mark
Comments: 1
Category: Grid
Type: Feature Request
1
It would be very help full to have the ability to summarize numeric columns in the Grid and display at the bottom of the Grid.
Completed
Last Updated: 02 Oct 2019 07:19 by ADMIN
Release 2.0.0
Created by: Ramon
Comments: 0
Category: Grid
Type: Bug Report
1

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; }
    }
}

Duplicated
Last Updated: 02 Mar 2020 13:13 by ADMIN
Created by: Peter
Comments: 2
Category: Grid
Type: Feature Request
1
The scenario is that a user has set various filter and sort options in a grid and when they select an item in the grid and click a custom edit or add button, we navigate them to a separate page to complete the add or edit action. When they have completed the add or edit, we want to navigate them back to the page with the grid and restore whatever filter, sort, page, and page size they had set in the grid prior to navigating away. The page and page size are easy enough to do since the grid allows binding to those parameters but the grid does not allow you to bind to the sort or filter options.
Completed
Last Updated: 14 Nov 2024 09:27 by ADMIN
Release 7.0.0

You can work around this by disabling virtual scrolling with something like this:

ScrollMode="@(Data.Count() > 30 ? GridScrollMode.Virtual : GridScrollMode.Scrollable)"