If the "Navigable" parameter of the Grid is set to false (its default state) and the EditMode is PopUp, there is no focus on the first input in Add/Edit mode.
Hi,
I am using a Blazor TelerikGrid component with Virtual ScrollMode. I have set a fixed Height, PageSize that exceeds the rows that fit in the grid, and a RowHeight which I have confirmed fits the row contents and resolves to a computed Height of the same value (using Chrome Dev Tools -> Computed tab). Everything works fine except that sometimes scrolling does not trigger the OnRead event and the rows displayed after scrolling are placeholders.
I don't experience this problem when I click the scroll arrow buttons (up or down). I don't experience the problem at all if I drag the scroll bar up or down. But if I page up/down, or click on the scroll page area up/down it will sometimes work and sometimes not. If placeholders are shown, I only need to click a scroll button up/down a few times for it to then read and display the correct rows.
To reproduce use the attached VS2019 project, click "Telerik Scroll Issue" nav menu, and in the TelerikGrid click the page down areas of the vertical scrollbar 3 times.
<AdminEdit>
Using the keyboard to save items works inconsistently. When editing an item, hitting enter seems to save the change as expected. When inserting an item, however, the item is lost.
---
ADMIN EDIT
Tthe grid calls the OnUpdate handler again, not OnCreate which results in data loss - the newly inserted item is unlikely to match existing data and so it appears to be lost.
Workaround - call the OnCreate handler yourself when the ID of the record is the default for its type - for example, zero for an integer. This indicates a newly inserted record in the grid.
<TelerikGrid Data=@MyData EditMode="@GridEditMode.Inline" Pageable="true" Height="500px" Navigable="true"
OnUpdate="@UpdateHandler" OnDelete="@DeleteHandler" OnCreate="@CreateHandler" OnCancel="@CancelHandler">
<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" />
<GridCommandColumn>
<GridCommandButton Command="Save" Icon="save" ShowInEdit="true">Update</GridCommandButton>
<GridCommandButton Command="Edit" Icon="edit">Edit</GridCommandButton>
<GridCommandButton Command="Delete" Icon="delete">Delete</GridCommandButton>
<GridCommandButton Command="Cancel" Icon="cancel" ShowInEdit="true">Cancel</GridCommandButton>
</GridCommandColumn>
</GridColumns>
</TelerikGrid>
@code {
async Task UpdateHandler(GridCommandEventArgs args)
{
SampleData item = (SampleData)args.Item;
if (item.ID == 0)
{
await CreateHandler(args);
}
else
{
// 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.");
}
async Task CancelHandler(GridCommandEventArgs args)
{
SampleData item = (SampleData)args.Item;
// if necessary, perform actual data source operation here through your service
Console.WriteLine("Cancel 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 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()
{
if (_data.Count < 1)
{
for (int i = 1; i < 50; i++)
{
_data.Add(new SampleData()
{
ID = i,
Name = "Name " + i.ToString()
});
}
}
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);
}
}
}
---
Values of FilterMenu are not preserved in GridState.
If FilterRow is used instead of FilterMenu then the values are preserved in GridState.
(I believe that Filtering was preserved with FilterMenu as well in some previous version but I could be wrong.)
Regards,
René
If in a grid columns are bound to integer values which shall be treated as enum values it can be done with the FieldType parameter.
Unfortunately the new FilterMenuType.CheckBoxList does not work as expected then.
With
<GridColumn Field="@(nameof(MyModel.MyPropertyId))"
FieldType="@(typeof(MyPropertyEnum))"
Title="MyProperty"
FilterMenuType="@FilterMenuType.CheckBoxList">
the filter shows Integers instead of Enum-Strings.
(With FilterMenuType.Menu the filter correctly treats the values as enums)
Regards,
René
If a new item for a grid is created and the CreateHandler is cancelled due to some validation error, the new loading indicator does not disappear.
protected async void CreateHandler(GridCommandEventArgs args)
{
var myItem = (MyModel) args.Item;
if (!IsValid(myItem))
{
args.IsCancelled = true;
return;
}
...
}
Regards,
René
This isn't a bug per say, but with the latest Telerik Blazor update, the GridCommandEventArgs Field and Value properties are now deprecated. When updating a specific cell in a grid using InCell edit mode, how am I able to know which specific field and value are updated when the OnUpdate event gets called? Before the latest update, I had the following code:
protected override void OnGridRowUpdate(GridCommandEventArgs args)
{
validationMessage = ValidateField(args.Field, args.Value);
}
I realize I have the updated values using args.Item, but I don't want to have to validate the entire row every time I update a cell. Is there still a way to know what cell I updated, or is that information no more?
Thank you,
Steve
The grid should support INotifyPropertyChanged for the objects in the grid, i.e. if the data object implements INotifyPropertyChanged and a property value changes, the corresponding cell value in the grid should also change.
When the Grid/TreeList is in incell edit mode and you finish editing a cell by pressing "Enter", the focus is lost if the next cell to be edited is not editable.
Steps to reproduce:
@using System.ComponentModel.DataAnnotations;
<TelerikGrid Data="@forecasts"
Height="550px"
FilterMode="@GridFilterMode.FilterMenu"
Sortable="true"
Pageable="true"
PageSize="20"
Groupable="true" Resizable="true"
Reorderable="true"
EditMode="@GridEditMode.Incell">
<GridColumns>
<GridColumn Field="Id" Title="Id" Width="100px" Editable="false" Groupable="false" />
<GridColumn Field="Summary" Id="summary" Title="telerik bind-Value">
<Template>
@{
var model = context as WeatherForecast;
<span>@model.Summary</span>
}
</Template>
<EditorTemplate>
@{
var model = context as WeatherForecast;
if (model.CanEdit)
{
<TelerikTextBox @bind-Value="@model.Summary"></TelerikTextBox>
}
else
{
@model.Summary
}
}
</EditorTemplate>
</GridColumn>
</GridColumns>
</TelerikGrid>
@code {
List<WeatherForecast> forecasts { get; set; }
protected override void OnInitialized()
{
forecasts = WeatherForecast.GetForecastList();
}
public class WeatherForecast
{
public int Id { get; set; }
public string Summary { get; set; }
public bool CanEdit { get; set; }
static public List<WeatherForecast> GetForecastList()
{
var rng = new Random();
return Enumerable.Range(1, 150).Select(index => new WeatherForecast
{
Id = index,
Summary = Summaries[rng.Next(Summaries.Length)],
CanEdit = index % 3 != 0
}).ToList();
}
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
}
}
The focus is lost
The focus should not be lost
All
All
x.y.z
x.y.z
If you reorder a column and then lock it, visually it looks locked and the functionality for a locked column is correctly supported.
However, the Locked property of the ColumnStates in Grid State for that column remains "false". Locked = "true" is applied based on the initial column position.
Currently, when navigation is used with virtual columns and locked columns, clicking on a cell, scrolls the cell to the center. The behavior was designed to have consistent interaction with either mouse, or keyboard. However, for mouse interaction such scrolling and changing the cell position according to the mouse cursor is not intuitive.
This bug report will target the scenario with mouse click for cells that are not overlapped by locked columns - they will not be scrolled to the center.