# Grid Events

This article explains the events available in the Telerik Grid for Blazor. They are grouped logically.

* [CUD Events](https://www.telerik.com/blazor-ui/documentation/components/grid/events#cud-events) - events related to Creating, Updating and Deleting items
* [Read Event](https://www.telerik.com/blazor-ui/documentation/components/grid/events#read-event) - event related to obtaining data
* [State Events](https://www.telerik.com/blazor-ui/documentation/components/grid/events#state-events)
* [Column Events](https://www.telerik.com/blazor-ui/documentation/components/grid/events#column-events)
* [Command Button Click](https://www.telerik.com/blazor-ui/documentation/components/grid/events#command-button-click)
* [Export Events](https://www.telerik.com/blazor-ui/documentation/components/grid/events#export-events)
* [OnModelInit](https://www.telerik.com/blazor-ui/documentation/components/grid/events#onmodelinit)
* [OnRowClick](https://www.telerik.com/blazor-ui/documentation/components/grid/events#onrowclick)
* [OnRowDoubleClick](https://www.telerik.com/blazor-ui/documentation/components/grid/events#onrowdoubleclick)
* [OnRowContextMenu](https://www.telerik.com/blazor-ui/documentation/components/grid/events#onrowcontextmenu)
* [OnRowExpand](https://www.telerik.com/blazor-ui/documentation/components/grid/events#onrowexpand)
* [OnRowCollapse](https://www.telerik.com/blazor-ui/documentation/components/grid/events#onrowcollapse)
* [OnRowRender](https://www.telerik.com/blazor-ui/documentation/components/grid/events#onrowrender)
* [OnRowDrop](https://www.telerik.com/blazor-ui/documentation/components/grid/events#onrowdrop)
* [PageChanged](https://www.telerik.com/blazor-ui/documentation/components/grid/events#pagechanged)
* [PageSizeChanged](https://www.telerik.com/blazor-ui/documentation/components/grid/events#pagesizechanged)
* [SelectedItemsChanged](https://www.telerik.com/blazor-ui/documentation/components/grid/events#selecteditemschanged)
* [SelectedCellsChanged](https://www.telerik.com/blazor-ui/documentation/components/grid/events#selectedcellschanged)

## CUD Events

The `OnAdd`, `OnCreate`, `OnUpdate` and `OnDelete` events let you get the data item that the user changed so you can transfer the user action to the actual data source.

The `OnEdit` and `OnCancel` events let you respond to user actions - when they want to edit an item and when the want to cancel changes on an item they have been editing. You can use them to, for example, prevent editing of certain items based on some condition.

You can read more about the CUD events in the [Editing Overview](https://www.telerik.com/blazor-ui/documentation/components/grid/editing/overview) article.

## Read Event

In the common case, you provide all the data to the Grid's `Data` collection and the Grid performs operations like paging, filtering, sorting on it for you. In some cases you may want to do this with your own code (for example, to retrieve only a small number of items in order to improve the backend performance). You can do this by handling the `OnRead` event where you can perform all the data read operations in the Grid. Read more about the [`OnRead` event fundamentals](https://www.telerik.com/blazor-ui/documentation/common-features/data-binding/onread) and check the article about [Manual Data Source Operations with the Grid](https://www.telerik.com/blazor-ui/documentation/components/grid/manual-operations).

## State Events

The grid state lets you control through code the aspects of the grid the user can control in the UI - such as filtering, sorting, grouping. The grid provides two events related to the state:

* `OnStateInit` - fires when the grid initializes so you can provide a stored version of the grid.

* `OnStateChanged` - fires when the user performs an action so you can see what area was changed and, if needed, alter the grid state.

Review the [grid state](https://www.telerik.com/blazor-ui/documentation/components/grid/state) article for more details and examples on how the grid state works and what you can do with it.

## Column Events

The Grid columns emit the `OnCellRender` event, so you can customize each cell separately. Read more and find examples in the [Grid Column Events](https://www.telerik.com/blazor-ui/documentation/components/grid/columns/events) article.

## Command Button Click

The command buttons of a grid provide an `OnClick` event before firing their built-in command (such as opening a row for editing, or adding a new row). You can do this to implement some additional logic and to also handle custom commands - both from a [Command Column](https://www.telerik.com/blazor-ui/documentation/components/grid/columns/command), and from a [Toolbar Button](https://www.telerik.com/blazor-ui/documentation/components/grid/toolbar)

## Export Events

During export, the Grid will fire events like `OnBeforeExport` and `OnAfterExport`. They allow you to:

* Get or modify the columns and their settings;
* Provide custom data;
* Cancel the export;
* Get the final file output;

Read more about them and find code examples in the [Grid Export Events](https://www.telerik.com/blazor-ui/documentation/components/grid/export/events) article.

## OnModelInit

The `OnModelInit` event fires before editing and adding new item in the component. The event allows you to:

* bind the component to a class that has no parameterless constructor

* bind the component to an interface

* bind the component to an abstract class

To achieve the desired behavior you can provide an instance of the model that the component is bound to in the `OnModelInit` event handler.

> caption The different use-cases of the OnModelInit event

```RAZOR.skip-repl NoParameterlessConstructor
@* Bind the Grid to a class without a parameterless constructor *@

<TelerikGrid Data="@SampleGridData"
             AutoGenerateColumns="true"
             Pageable="true"
             PageSize="10"
             FilterMode="@GridFilterMode.FilterMenu"
             EditMode="@GridEditMode.Incell"
             OnModelInit="@OnModelInitHandler"
             OnUpdate="@UpdateHandler"
             OnDelete="@DeleteHandler"
             OnCreate="@CreateHandler"
             OnCancel="@CancelHandler">
    <GridColumns>
        <GridAutoGeneratedColumns />
        <GridCommandColumn>
            <GridCommandButton Command="Delete" Icon="@SvgIcon.Trash">Delete</GridCommandButton>
        </GridCommandColumn>
    </GridColumns>
</TelerikGrid>

@code {
    private List<SampleData> SampleGridData { get; set; }

    private SampleData OnModelInitHandler()
    {
        return new SampleData(1, "Sample Text", DateTime.Now);
    }

    async Task UpdateHandler(GridCommandEventArgs args)
    {
        SampleData item = (SampleData)args.Items.First();

        // perform actual data source operations here through your service
        await MyService.Update(item);

        // update the local view-model data with the service data
        await GenerateSampleData();
    }

    async Task DeleteHandler(GridCommandEventArgs args)
    {
        SampleData item = (SampleData)args.Items.First();

        await MyService.Delete(item);

        await GenerateSampleData();

        Console.WriteLine("Delete event is fired.");
    }

    async Task CreateHandler(GridCommandEventArgs args)
    {
        SampleData item = (SampleData)args.Items.First();

        // perform actual data source operation here through your service
        await MyService.Create(item);

        // update the local view-model data with the service data
        await GenerateSampleData();
    }

    void CancelHandler(GridCommandEventArgs args)
    {
        SampleData item = (SampleData)args.Items.First();
    }

    protected override async Task OnInitializedAsync()
    {
        await GenerateSampleData();
    }

    private async Task GenerateSampleData()
    {
        SampleGridData = await MyService.Read();
    }

    public class SampleData
    {
        public int SampleId { get; set; }
        public string SampleText { get; set; }
        public DateTime SampleDate { get; set; }

        public SampleData(int id, string text, DateTime date)
        {
            SampleId = id;
            SampleText = text;
            SampleDate = date;
        }
    }

    public static class MyService
    {
        private static List<SampleData> _data { get; set; } = new List<SampleData>();

        public static async Task Create(SampleData itemToInsert)
        {
            itemToInsert.SampleId = _data.Count + 1;
            _data.Insert(0, itemToInsert);
        }

        public static async Task<List<SampleData>> Read()
        {
            if (_data.Count < 1)
            {
                for (int i = 1; i < 50; i++)
                {
                    _data.Add(new SampleData(i, $"Text {i}", DateTime.Today.AddDays(i)));
                }
            }

            return await Task.FromResult(_data);
        }

        public static async Task Update(SampleData itemToUpdate)
        {
            var index = _data.FindIndex(i => i.SampleId == itemToUpdate.SampleId);
            if (index != -1)
            {
                _data[index] = itemToUpdate;
            }
        }

        public static async Task Delete(SampleData itemToDelete)
        {
            _data.Remove(itemToDelete);
        }
    }
}
```

```RAZOR Interface
@* Bind the Grid to an interface *@

<TelerikGrid Data="@SampleGridData"
             AutoGenerateColumns="true"
             Pageable="true"
             PageSize="10"
             FilterMode="@GridFilterMode.FilterMenu"
             EditMode="@GridEditMode.Incell"
             OnModelInit="@OnModelInitHandler"
             OnUpdate="@UpdateHandler"
             OnDelete="@DeleteHandler"
             OnCreate="@CreateHandler"
             OnCancel="@CancelHandler">
    <GridColumns>
        <GridAutoGeneratedColumns />
        <GridCommandColumn>
            <GridCommandButton Command="Delete" Icon="@SvgIcon.Trash">Delete</GridCommandButton>
        </GridCommandColumn>
    </GridColumns>
</TelerikGrid>

@code {
    private List<ISampleData> SampleGridData { get; set; }

    private SampleData OnModelInitHandler()
    {
        return new SampleData(1, "Sample Text", DateTime.Now);
    }

    async Task UpdateHandler(GridCommandEventArgs args)
    {
        SampleData item = (SampleData)args.Items.First();

        // perform actual data source operations here through your service
        await MyService.Update(item);

        // update the local view-model data with the service data
        await GenerateSampleData();
    }

    async Task DeleteHandler(GridCommandEventArgs args)
    {
        SampleData item = (SampleData)args.Items.First();

        await MyService.Delete(item);

        await GenerateSampleData();

        Console.WriteLine("Delete event is fired.");
    }

    async Task CreateHandler(GridCommandEventArgs args)
    {
        SampleData item = (SampleData)args.Items.First();

        // perform actual data source operation here through your service
        await MyService.Create(item);

        // update the local view-model data with the service data
        await GenerateSampleData();
    }

    void CancelHandler(GridCommandEventArgs args)
    {
        SampleData item = (SampleData)args.Items.First();
    }

    protected override async Task OnInitializedAsync()
    {
        await GenerateSampleData();
    }

    private async Task GenerateSampleData()
    {
        SampleGridData = await MyService.Read();
    }

    public interface ISampleData
    {
        public int SampleId { get; set; }
        public string SampleText { get; set; }
    }

    public class SampleData : ISampleData
    {
        public int SampleId { get; set; }
        public string SampleText { get; set; }
        public DateTime SampleDate { get; set; }

        public SampleData(int id, string text, DateTime date)
        {
            SampleId = id;
            SampleText = text;
            SampleDate = date;
        }
    }

    public static class MyService
    {
        private static List<ISampleData> _data { get; set; } = new List<ISampleData>();

        public static async Task Create(SampleData itemToInsert)
        {
            itemToInsert.SampleId = _data.Count + 1;
            _data.Insert(0, itemToInsert);
        }

        public static async Task<List<ISampleData>> Read()
        {
            if (_data.Count < 1)
            {
                for (int i = 1; i < 50; i++)
                {
                    _data.Add(new SampleData(i, $"Text {i}", DateTime.Today.AddDays(i)));
                }
            }

            return await Task.FromResult(_data);
        }

        public static async Task Update(SampleData itemToUpdate)
        {
            var index = _data.FindIndex(i => i.SampleId == itemToUpdate.SampleId);
            if (index != -1)
            {
                _data[index] = itemToUpdate;
            }
        }

        public static async Task Delete(SampleData itemToDelete)
        {
            _data.Remove(itemToDelete);
        }
    }
}
```

```RAZOR AbstractClass
@* Bind the Grid to an abstract class *@

<TelerikGrid Data="@SampleGridData"
             AutoGenerateColumns="true"
             Pageable="true"
             PageSize="10"
             FilterMode="@GridFilterMode.FilterMenu"
             EditMode="@GridEditMode.Incell"
             OnModelInit="@OnModelInitHandler"
             OnUpdate="@UpdateHandler"
             OnDelete="@DeleteHandler"
             OnCreate="@CreateHandler"
             OnCancel="@CancelHandler">
    <GridColumns>
        <GridAutoGeneratedColumns />
        <GridCommandColumn>
            <GridCommandButton Command="Delete" Icon="@SvgIcon.Trash">Delete</GridCommandButton>
        </GridCommandColumn>
    </GridColumns>
</TelerikGrid>

@code {
    private List<SampleDataBase> SampleGridData { get; set; }

    private SampleData OnModelInitHandler()
    {
        return new SampleData(1, "Sample Text", DateTime.Now);
    }

    async Task UpdateHandler(GridCommandEventArgs args)
    {
        SampleData item = (SampleData)args.Items.First();

        // perform actual data source operations here through your service
        await MyService.Update(item);

        // update the local view-model data with the service data
        await GenerateSampleData();
    }

    async Task DeleteHandler(GridCommandEventArgs args)
    {
        SampleData item = (SampleData)args.Items.First();

        await MyService.Delete(item);

        await GenerateSampleData();

        Console.WriteLine("Delete event is fired.");
    }

    async Task CreateHandler(GridCommandEventArgs args)
    {
        SampleData item = (SampleData)args.Items.First();

        // perform actual data source operation here through your service
        await MyService.Create(item);

        // update the local view-model data with the service data
        await GenerateSampleData();
    }

    void CancelHandler(GridCommandEventArgs args)
    {
        SampleData item = (SampleData)args.Items.First();
    }

    protected override async Task OnInitializedAsync()
    {
        await GenerateSampleData();
    }

    private async Task GenerateSampleData()
    {
        SampleGridData = await MyService.Read();
    }

    public abstract class SampleDataBase
    {
        public int SampleId { get; set; }
        public string SampleText { get; set; }
    }

    public class SampleData : SampleDataBase
    {
        public DateTime SampleDate { get; set; }

        public SampleData(int id, string text, DateTime date)
        {
            SampleId = id;
            SampleText = text;
            SampleDate = date;
        }
    }

    public static class MyService
    {
        private static List<SampleDataBase> _data { get; set; } = new List<SampleDataBase>();

        public static async Task Create(SampleData itemToInsert)
        {
            itemToInsert.SampleId = _data.Count + 1;
            _data.Insert(0, itemToInsert);
        }

        public static async Task<List<SampleDataBase>> Read()
        {
            if (_data.Count < 1)
            {
                for (int i = 1; i < 50; i++)
                {
                    _data.Add(new SampleData(i, $"Text {i}", DateTime.Today.AddDays(i)));
                }
            }

            return await Task.FromResult(_data);
        }

        public static async Task Update(SampleData itemToUpdate)
        {
            var index = _data.FindIndex(i => i.SampleId == itemToUpdate.SampleId);
            if (index != -1)
            {
                _data[index] = itemToUpdate;
            }
        }

        public static async Task Delete(SampleData itemToDelete)
        {
            _data.Remove(itemToDelete);
        }
    }
}
```

## OnRowClick

The `OnRowClick` event fires when the user:

* Clicks or taps on a data row.
* Hits Enter while the row has focus. This scenario requires enabled keyboard navigation (`Navigable="true"`).

The event *does not fire* when the user:

* Clicks or taps on a command button;
* Selects a row via the built-in checkbox column;
* Expands or collapses the hierarchy;
* When the clicked row is in edit mode.

`OnRowClick` event fires *before* selection.

The `OnRowClick` event handler receives a `GridRowClickEventArgs` argument, which has the following properties.

<style>
    .article table {
        table-layout: auto;
        word-break: normal;
    }
</style>

| Property       | Type        | Description                                                                                                                                                                                                                                                       |
| -------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `EventArgs`    | `EventArgs` | This object maps to `MouseEventArgs` or `KeyboardEventArgs` depending on the user action.                                                                                                                                                                         |
| `Field`        | `string`    | The `Field` parameter of the clicked column.                                                                                                                                                                                                                      |
| `Item`         | `object`    | The data item. Cast the object to your model type to access its members.                                                                                                                                                                                          |
| `ShouldRender` | `bool`      | Sets if the component will re-render after the event via `StateHasChanged()` call. This can be useful if you need to change the component parameters or state during the event execution, and especially if you need to execute async logic in the event handler. |

> caption Using the Grid OnRowClick event

<demo metaUrl="client/grid/events-row-click/" height="450"></demo>

## OnRowDoubleClick

The `OnRowDoubleClick` event fires when the user double-clicks or double-taps on a data row.

The event *does not fire* when the user:

* Clicks or taps on a command button;
* Selects a row via the built-in checkbox column;
* Expands or collapses the hierarchy;
* When the clicked row is in edit mode.

`OnRowDoubleClick` event fires *before* selection.

The `OnRowDoubleClick` event handler receives a `GridRowClickEventArgs` argument, which has the following properties.

<style>
    .article table {
        table-layout: auto;
        word-break: normal;
    }
</style>

| Property       | Type        | Description                                                                                                                                                                                                                                                       |
| -------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `EventArgs`    | `EventArgs` | This object maps to `MouseEventArgs` or `KeyboardEventArgs` depending on the user action.                                                                                                                                                                         |
| `Field`        | `string`    | The `Field` parameter of the clicked column.                                                                                                                                                                                                                      |
| `Item`         | `object`    | The data item. Cast the object to your model type to access its members.                                                                                                                                                                                          |
| `ShouldRender` | `bool`      | Sets if the component will re-render after the event via `StateHasChanged()` call. This can be useful if you need to change the component parameters or state during the event execution, and especially if you need to execute async logic in the event handler. |

> caption Using the Grid OnRowDoubleClick event

<demo metaUrl="client/grid/events-row-double-click/" height="450"></demo>

## OnRowContextMenu

The `OnRowContextMenu` event fires when the user:

* Right-clicks or taps-and-holds a data row;
* Hits the context menu keyboard button while the row has focus. This scenario requires enabled keyboard navigation (`Navigable="true"`).

Use `OnRowContextMenu` to [integrate the Context menu](https://www.telerik.com/blazor-ui/documentation/components/contextmenu/integration#context-menu-for-a-grid-row) with the table rows.

The `OnRowContextMenu` event handler receives a `GridRowClickEventArgs` argument, which has the following properties.

<style>
    .article table {
        table-layout: auto;
        word-break: normal;
    }
</style>

| Property       | Type        | Description                                                                                                                                                                                                                                                       |
| -------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `EventArgs`    | `EventArgs` | This object maps to `MouseEventArgs` or `KeyboardEventArgs` depending on the user action.                                                                                                                                                                         |
| `Field`        | `string`    | The `Field` parameter of the clicked column.                                                                                                                                                                                                                      |
| `Item`         | `object`    | The data item. Cast the object to your model type to access its members.                                                                                                                                                                                          |
| `ShouldRender` | `bool`      | Sets if the component will re-render after the event via `StateHasChanged()` call. This can be useful if you need to change the component parameters or state during the event execution, and especially if you need to execute async logic in the event handler. |

> caption Using the Grid OnRowContextMenu event

<demo metaUrl="client/grid/events-row-context-menu/" height="450"></demo>

## OnRowExpand

The `OnRowExpand` event fires as a response to the user expanding the [`DetailTemplate`](https://www.telerik.com/blazor-ui/documentation/components/grid/hierarchy) of the Grid.

The event handler receives a `GridRowExpandEventArgs` object which provides the model of the clicked row in the `Item` field that you can cast to your model type.

If you set the `ShouldRender` field of the event arguments to `true`, the component will re-render after the event (it will call `StateHasChanged()`). This can be useful if you need to change its parameters or state during the event execution and especially if you need to execute `async` logic in the event handler.

> caption Use the OnRowExpand event to load detailed data on demand. Another approach can be found on our [public github repository](https://github.com/telerik/blazor-ui/tree/master/grid/load-on-demand-hierarchy).

<demo metaUrl="client/grid/events-row-expand/" height="600"></demo>

## OnRowCollapse

The `OnRowCollapse` event fires as a response to the user collapsing the [`DetailTemplate`](https://www.telerik.com/blazor-ui/documentation/components/grid/hierarchy) of the Grid.

The event handler receives a `GridRowCollapseEventArgs` object which provides the model of the clicked row in the `Item` field that you can cast to your model type.

If you set the `ShouldRender` field of the event arguments to `true`, the component will re-render after the event (it will call `StateHasChanged()`). This can be useful if you need to change its parameters or state during the event execution and especially if you need to execute `async` logic in the event handler.

> caption Use the OnRowCollapse event to get the Id of the collapsed row from the data model

<demo metaUrl="client/grid/events-row-collapse/" height="650"></demo>

## OnRowRender

This event fires when each Grid row renders. This can happen in the following cases:

* Initial Grid data binding and subsequent data operations (paging, sorting, etc.).
* A command button is clicked. This includes entering and exiting edit mode, but also custom commands.
* During typing in edit mode, but only if the column has an `EditorTemplate`.
* A child component inside a column `Template` fires an `EventCallback`.

`OnRowRender` receives an argument of type `GridRowRenderEventArgs` which exposes the following fields:

* `Item` - an object you can cast to your model class to obtain the current data item.
* `Class` - the custom CSS class that will be applied to the table row.

> caption Use the OnRowRender event to apply custom styles to Grid rows based on certain condition

<demo metaUrl="client/grid/events-row-render/" height="500"></demo>

## OnRowDrop

The `OnRowDrop` event fires when the user drags and drops rows in the grid or between grids. You can read more on setting it up and using the grid row dragging feature in the [Row Drag and Drop](https://www.telerik.com/blazor-ui/documentation/components/grid/row-drag-drop) article.

## PageChanged

The event fires when the user pages the grid.

> caption Handle the PageChanged event to know when the user changes the page

<demo metaUrl="client/grid/events-page-changed/" height="400"></demo>

> caption One-way binding of the Page parameter should be used with the PageChanged event to keep the view-model in sync

<demo metaUrl="client/grid/events-page-binding/" height="400"></demo>

## PageSizeChanged

The `PageSizeChanged` event fires when the user changes the page size via the pager DropDownList. The existence of this event also ensures that the Grid `PageSize` attribute supports two-way binding.

If the user selects the "All" option from the page size DropDownList, the `PageSizeChanged` event will receive the total item count as an argument.

Make sure to update the current page size when using the event.

> caption Handle PageSizeChanged

<demo metaUrl="client/grid/events-page-size-changed/" height="450"></demo>

## SelectedItemsChanged

Fires when [row selection is enabled](https://www.telerik.com/blazor-ui/documentation/components/grid/selection/overview#enable-row-or-cell-selection) and the user selects or deselects one row or multiple rows, depending on the [selection mode](https://www.telerik.com/blazor-ui/documentation/components/grid/selection/overview#use-single-or-multiple-selection).

Visit the [Grid Row Selection article to see an example](https://www.telerik.com/blazor-ui/documentation/components/grid/selection/rows#selecteditemschanged-event).

## SelectedCellsChanged

Fires when [cell selection is enabled](https://www.telerik.com/blazor-ui/documentation/components/grid/selection/overview#enable-row-or-cell-selection) and the user selects or deselects one cell or multiple cells, depending on the [selection mode](https://www.telerik.com/blazor-ui/documentation/components/grid/selection/overview#use-single-or-multiple-selection).

Visit the [Grid Cell Selection article to see an example](https://www.telerik.com/blazor-ui/documentation/components/grid/selection/cells#selectedcellschanged-event).

## See Also

* [Grid Overview](https://www.telerik.com/blazor-ui/documentation/components/grid/overview)
* [Grid Editing Overview](https://www.telerik.com/blazor-ui/documentation/components/grid/editing/overview)
* [Grid Column Events](https://www.telerik.com/blazor-ui/documentation/components/grid/columns/events)
* [Manual Data Source Operations](https://www.telerik.com/blazor-ui/documentation/components/grid/manual-operations)
* [Blazor Grid](https://www.telerik.com/blazor-ui/documentation/components/grid/overview)
