# Edit Grid CheckBoxes with Single Click

## Environment

<table>
    <tbody>
        <tr>
            <td>Product</td>
            <td>
                Grid for Blazor, <br />
                TreeList for Blazor
            </td>
        </tr>
    </tbody>
</table>

## Description

This KB article answers the following questions:

* To edit a checkbox in a Grid cell, users need to click once to put the row (or cell) in edit mode. Then they need another click to change the checkbox value. How to do this with only one click?
* How to update boolean values in the Grid with no edit mode?
* How to toggle checkboxes in the Grid directly without using the built-in editing feature?
* How to allow users to check and uncheck checкbox values when the Grid is not editable?
* How to use a single click on Grid checkboxes to set the reverse (opposite) value?
* How to get the value of a checkbox and use it for an update action on button click?

## Solution

1. Define a [`<GridColumn>` with a `Field`](https://www.telerik.com/blazor-ui/documentation/components/grid/columns/bound) that points to a `bool` property.
2. Set [`Editable="false"`](https://www.telerik.com/blazor-ui/documentation/components/grid/columns/bound#data-operations) for that column, if the [Grid `EditMode`](https://www.telerik.com/blazor-ui/documentation/components/grid/editing/overview) is `Incell`.
3. Define a [column cell template](https://www.telerik.com/blazor-ui/documentation/components/grid/templates/column) (`<Template>`) for the column. Place a [`TelerikCheckBox` component](https://www.telerik.com/blazor-ui/documentation/components/checkbox/overview) inside.
4. If the updated CheckBox values require real-time synchronization with a remote data source, then use the [CheckBox `OnChange` or `ValueChanged` event](https://www.telerik.com/blazor-ui/documentation/components/checkbox/events). In this case, `ValueChanged` will also require a [`ValueExpression`](https://www.telerik.com/blazor-ui/documentation/knowledge-base/requires-valueexpression).

```CSHTML
@using Telerik.DataSource.Extensions

<TelerikGrid OnRead="@OnGridRead"
             TItem="@User"
             EditMode="@GridEditMode.Incell"
             OnUpdate="@OnGridUpdate"
             OnCreate="@OnGridCreate">
    <GridToolBarTemplate>
        <GridCommandButton Command="Add">Add</GridCommandButton>
    </GridToolBarTemplate>
    <GridColumns>
        <GridColumn Field="@nameof(User.Name)" />
        <GridColumn Field="@nameof(User.Admin)" Title="No Template" />
        <GridColumn Field="@nameof(User.Admin)" Title="Template - ValueChanged" Editable="false">
            <Template>
                @{
                    var user = (User)context;
                }
                <TelerikCheckBox Value="@user.Admin"
                                 ValueExpression="@( () => user.Admin )"
                                 ValueChanged="@( (bool newValue) => OnAdminValueChanged(newValue, user) )" />
            </Template>
        </GridColumn>
        <GridColumn Field="@nameof(User.Admin)" Title="Template - OnChange" Editable="false">
            <Template>
                @{
                    var user = (User)context;
                }
                <TelerikCheckBox @bind-Value="@user.Admin"
                                 OnChange="@( (object newValue) => OnAdminChange((bool)newValue, user) )" />
            </Template>
        </GridColumn>
    </GridColumns>
</TelerikGrid>

@code {
    private List<User> Users { get; set; } = new();

    private int LastId { get; set; }

    private async Task OnAdminValueChanged(bool newValue, User user)
    {
        // Update the local value in the Grid.
        // Required when using a ValueChanged handler.
        user.Admin = newValue;

        // Update the remote data source.
        await TriggerGridUpdate(user);
    }

    private async Task OnAdminChange(bool newValue, User user)
    {
        // Update the remote data source.
        await TriggerGridUpdate(user);
    }

    private async Task TriggerGridUpdate(User user)
    {
        // Here we simulate an actual Grid update.
        // The goal is to reuse the existing OnUpdate event handler.
        // However, such OnUpdate simulation is not required.
        // Instead, you can call the remote data service directly.
        await OnGridUpdate(new GridCommandEventArgs()
        {
            Field = nameof(User.Admin),
            IsNew = false,
            Items = new List<User>() { user },
            Value = user.Admin
        });
    }

    private async Task OnGridUpdate(GridCommandEventArgs args)
    {
        // simulate network delay
        await Task.Delay(100);

        var user = (User)args.Items.First();
        var index = Users.FindIndex(x => x.Id == user.Id);

        if (index >= 0)
        {
            Users[index] = user;
        }
    }

    private async Task OnGridCreate(GridCommandEventArgs args)
    {
        // simulate network delay
        await Task.Delay(100);

        var user = (User)args.Items.First();
        user.Id = ++LastId;

        Users.Insert(0, user);
    }

    private async Task OnGridRead(GridReadEventArgs args)
    {
        // simulate network delay
        await Task.Delay(100);

        var result = Users.ToDataSourceResult(args.Request);

        args.Data = result.Data;
        args.Total = result.Total;
    }

    protected override void OnInitialized()
    {
        Users = new List<User>();

        for (int i = 1; i <= 3; i++)
        {
            Users.Add(new User()
            {
                Id = ++LastId,
                Name = "User Name " + LastId,
                Admin = LastId % 2 == 0
            });
        }

        base.OnInitialized();
    }

    public class User
    {
        public int Id { get; set; }
        public string Name { get; set; } = string.Empty;
        public bool Admin { get; set; }
    }
}
```

## Notes

The above custom editing mechanism can be used for all data types like `string`, `int`, `double`, `decimal`, `DateTime`, `enum`, and so on. However, it also avoids the standard Grid editing feature, which causes the following side effects and limitations:

* The [Grid `OnEdit` and `OnUpdate` events](https://www.telerik.com/blazor-ui/documentation/components/grid/editing/overview#events) does not fire when editing in a Grid column `<Template>`.
* The [Grid `OnCancel` event](https://www.telerik.com/blazor-ui/documentation/components/grid/editing/overview#events) does not fire either. The Grid does not create a [copy of the original data item](https://www.telerik.com/blazor-ui/documentation/components/grid/editing/overview#item-instances), so users cannot revert their changes.
* If the Grid displays custom edit cells next to standard edit cells, then the built-in [Grid keyboard navigation (tabbing)](https://www.telerik.com/blazor-ui/documentation/components/grid/keyboard-navigation) across these two cell types does not work.
* Value changes in standard edit cells are applied to template columns that are bound to the same model property *after* the `OnUpdate` handler executes. This is because the [built-in Grid editing](https://www.telerik.com/blazor-ui/documentation/components/grid/editing/overview) creates a [copy of the original data item](https://www.telerik.com/blazor-ui/documentation/components/grid/editing/overview#item-instances) while a row is in edit mode.

## See Also

* [Edit All Grid Rows and Cells](https://www.telerik.com/blazor-ui/documentation/knowledge-base/grid-edit-all-rows-cells)
* [Grid Column Cell Template](https://www.telerik.com/blazor-ui/documentation/components/grid/templates/column)
