Customers report inconsistent in-cell editing behavior with DatePicker columns in the Grid.
Here is a REPL test page that reproduces the issue (first date column) and provides a workaround (second date column):
https://blazorrepl.telerik.com/QAErkrEh090ykIxR16
The workaround relies on Grid EditorTemplate, the DatePicker OnClose event, and programmatic Grid edit mode management. The relevant code is:
@using System.ComponentModel.DataAnnotations
<TelerikGrid @ref="@GridRef"
Data="@GridData"
EditMode="@GridEditMode.Incell"
OnUpdate="@OnGridUpdate"
OnCreate="@OnGridCreate">
<GridToolBarTemplate>
<GridCommandButton Command="Add">Add Item</GridCommandButton>
</GridToolBarTemplate>
<GridColumns>
<GridColumn Field="@nameof(Product.Name)" />
<GridColumn Field="@nameof(Product.StartDate)" Title="BUG" DisplayFormat="{0:d}" />
<GridColumn Field="@nameof(Product.EndDate)" Title="WORKAROUND" DisplayFormat="{0:d}">
<EditorTemplate>
@{ var editItem = (Product)context; }
<TelerikDatePicker Value="editItem.EndDate"
ValueChanged="@((DateTime? newValue) => OnGridDatePickerValueChanged(newValue, editItem))"
ValueExpression="@( () => editItem.EndDate )"
OnClose="@(async () => await OnGridDatePickerClose(editItem))" />
</EditorTemplate>
</GridColumn>
</GridColumns>
</TelerikGrid>
@code {
#nullable enable
private TelerikGrid<Product>? GridRef;
private List<Product> GridData { get; set; } = new();
private int LastId { get; set; }
private DateTime LastDatePickerValueChanged { get; set; } = DateTime.Now;
private void OnGridDatePickerValueChanged(DateTime? newValue, Product editItem)
{
editItem.EndDate = newValue;
LastDatePickerValueChanged = DateTime.Now;
}
private async Task OnGridDatePickerClose(Product editItem)
{
if (DateTime.Now - LastDatePickerValueChanged > TimeSpan.FromMilliseconds(500))
{
GridState<Product> gridState = GridRef!.GetState();
if (gridState.EditItem is not null && gridState.EditItem.Id == editItem.Id)
{
// Uncomment to perform an item update instead of cancel
// OnGridUpdate(new GridCommandEventArgs { Item = editItem });
gridState.OriginalEditItem = null!;
gridState.EditItem = null!;
await GridRef.SetStateAsync(gridState);
}
}
}
private void OnGridCreate(GridCommandEventArgs args)
{
var createdItem = (Product)args.Item;
createdItem.Id = ++LastId;
GridData.Insert(0, createdItem);
}
private void OnGridUpdate(GridCommandEventArgs args)
{
var updatedItem = (Product)args.Item;
var originalItemIndex = GridData.FindIndex(i => i.Id == updatedItem.Id);
if (originalItemIndex != -1)
{
GridData[originalItemIndex] = updatedItem;
}
}
protected override void OnInitialized()
{
for (int i = 1; i <= 5; i++)
{
GridData.Add(new Product()
{
Id = ++LastId,
Name = $"Product {LastId}",
Price = Random.Shared.Next(0, 100) * 1.23m,
Quantity = Random.Shared.Next(0, 1000),
StartDate = DateTime.Today.AddDays(-Random.Shared.Next(60, 1000)),
EndDate = DateTime.Today.AddDays(Random.Shared.Next(1, 60)),
IsActive = LastId % 4 > 0
});
}
}
public class Product
{
public int Id { get; set; }
[Required]
public string Name { get; set; } = string.Empty;
public decimal Price { get; set; }
public int Quantity { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public bool IsActive { get; set; }
}
}