I've found a bit of inconsistent behaviour in the InCell mode that I think is a bug?:
- If you click into a column bound to a boolean field, then click on another non-editable cell in the grid, this will not end the edit mode for the boolean column (so, it still shows a checkbox).
- Whereas, for a string or date column, if you click into the field and put it into edit mode, then click onto a non-editable area of the grid that will end the edit mode.
I think the second of those behaviours is correct and what a user would expect.
I've attached a gif showing what I mean. I'm on version 2.20.
This is the code for the example in the gif.
@page "/InCell"
@using Telerik.Blazor
@using Telerik.Blazor.Components
Click a cell, edit it and click outside of the cell to see the change.
<
br
/>
<
strong
>Editing is prevented for the first two items.</
strong
>
<
TelerikGrid
Data=@MyData
EditMode
=
"@GridEditMode.Incell"
Pageable
=
"true"
Height
=
"500px"
Sortable
=
"true"
OnUpdate
=
"@UpdateHandler"
OnEdit
=
"@EditHandler"
OnDelete
=
"@DeleteHandler"
OnCreate
=
"@CreateHandler"
>
<
GridToolBar
>
<
GridCommandButton
Command
=
"Add"
Icon
=
"add"
>Add Employee</
GridCommandButton
>
</
GridToolBar
>
<
GridColumns
>
<
GridColumn
Field=@nameof(SampleData.ID)
Title
=
"ID"
Editable
=
"false"
/>
<
GridColumn
Field=@nameof(SampleData.Name)
Title
=
"Name"
/>
<
GridColumn
Field=@nameof(SampleData.Happy) />
<
GridCommandColumn
>
<
GridCommandButton
Command
=
"Save"
Icon
=
"save"
ShowInEdit
=
"true"
>Update</
GridCommandButton
>
<
GridCommandButton
Command
=
"Delete"
Icon
=
"delete"
>Delete</
GridCommandButton
>
</
GridCommandColumn
>
</
GridColumns
>
</
TelerikGrid
>
@code {
void EditHandler(GridCommandEventArgs args)
{
SampleData item = (SampleData)args.Item;
// prevent opening for edit based on condition
if (item.ID <
3
)
{
args.IsCancelled
=
true
;// the general approach for cancelling an event
}
Console.WriteLine("Edit event is fired for column " + args.Field);
}
async Task UpdateHandler(GridCommandEventArgs args)
{
SampleData item = (SampleData)args.Item;
// perform actual data source operations here through your service
await MyService.Update(item);
// update the local view-model data with the service data
await GetGridData();
Console.WriteLine("Update event is fired.");
}
async Task DeleteHandler(GridCommandEventArgs args)
{
SampleData item = (SampleData)args.Item;
// perform actual data source operation here through your service
await MyService.Delete(item);
// update the local view-model data with the service data
await GetGridData();
Console.WriteLine("Delete event is fired.");
}
async Task CreateHandler(GridCommandEventArgs args)
{
SampleData item = (SampleData)args.Item;
// perform actual data source operation here through your service
await MyService.Create(item);
// update the local view-model data with the service data
await GetGridData();
Console.WriteLine("Create 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 bool Happy { get; set; }
}
public List<SampleData> MyData { get; set; }
async Task GetGridData()
{
MyData = await MyService.Read();
}
protected override async Task OnInitializedAsync()
{
await GetGridData();
}
// the following static class mimics an actual data service that handles the actual data source
// replace it with your actual service through the DI, this only mimics how the API can look like and works for this standalone page
public static class MyService
{
private static List<
SampleData
> _data { get; set; } = new List<
SampleData
>();
public static async Task Create(SampleData itemToInsert)
{
itemToInsert.ID = _data.Count + 1;
_data.Insert(0, itemToInsert);
}
public static async Task<
List
<SampleData>> Read()
{
var happy = false;
if (_data.Count <
1
)
{
for (int
i
=
1
; i < 50; i++)
{
happy = !happy;
_data.Add(new SampleData()
{
ID
=
i
,
Name
=
"Name "
+ i.ToString(),
Happy
=
happy
});
}
}
return await Task.FromResult(_data);
}
public static async Task Update(SampleData itemToUpdate)
{
var
index
=
_data
.FindIndex(i => i.ID == itemToUpdate.ID);
if (index != -1)
{
_data[index] = itemToUpdate;
}
}
public static async Task Delete(SampleData itemToDelete)
{
_data.Remove(itemToDelete);
}
}
}