Repro steps:
Actual: The "Name" field is blank
Expected: All fields have the appropriate data
Reproducible below, expected results is that after editing the decimal field you'll get the data under the grid. Actual: either it does not get updated, or the value is always 0.
@using Telerik.Blazor.Components.Grid<TelerikGrid Data=@MyData EditMode="incell" Pageable="true" Height="500px"> <TelerikGridEvents> <EventsManager OnUpdate="@UpdateHandler" OnEdit="@EditHandler" OnDelete="@DeleteHandler" OnCreate="@CreateHandler"></EventsManager> </TelerikGridEvents> <TelerikGridToolBar> <TelerikGridCommandButton Command="Add" Icon="add">Add Employee</TelerikGridCommandButton> </TelerikGridToolBar> <TelerikGridColumns> <TelerikGridColumn Field=@nameof(SampleData.ID) Title="ID" Editable="false" /> <TelerikGridColumn Field=@nameof(SampleData.Name) Title="Name" /> <TelerikGridColumn Field=@nameof(SampleData.SomeDecimal) Title="Some Decimal" /> <TelerikGridCommandColumn> <TelerikGridCommandButton Command="Delete" Icon="delete">Delete</TelerikGridCommandButton> <TelerikGridCommandButton Command="Save" Icon="save" ShowInEdit="true">Update</TelerikGridCommandButton> </TelerikGridCommandColumn> </TelerikGridColumns></TelerikGrid>@lastUpdateOnDecimal@code { public void EditHandler(GridCommandEventArgs args) { SampleData item = (SampleData)args.Item; Console.WriteLine("Edit event is fired for column " + args.Field); } string lastUpdateOnDecimal; public void UpdateHandler(GridCommandEventArgs args) { string fieldName = args.Field; object newVal = args.Value; //you can cast this, if necessary, according to your model SampleData item = (SampleData)args.Item;//you can also use the entire model //perform actual data source operation here //if you have a context added through an @inject statement, you could call its SaveChanges() method //myContext.SaveChanges(); if (fieldName == "SomeDecimal") { lastUpdateOnDecimal = $"decimal for {item.ID} updated to {newVal} on {DateTime.Now}"; } var matchingItem = MyData.FirstOrDefault(c => c.ID == item.ID); if (matchingItem != null) { matchingItem.Name = item.Name; } Console.WriteLine("Update event is fired for " + args.Field + " with value " + args.Value); } public void CreateHandler(GridCommandEventArgs args) { SampleData item = (SampleData)args.Item; //perform actual data source operation here item.ID = MyData.Count; MyData.Add(item); Console.WriteLine("Create event is fired."); } public void DeleteHandler(GridCommandEventArgs args) { SampleData item = (SampleData)args.Item; //perform actual data source operation here //if you have a context added through an @inject statement, you could call its SaveChanges() method //myContext.SaveChanges(); MyData.Remove(item); Console.WriteLine("Delete 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 decimal SomeDecimal { get; set; } } public List<SampleData> MyData { get; set; } protected override void OnInit() { MyData = new List<SampleData>(); for (int i = 0; i < 50; i++) { MyData.Add(new SampleData() { ID = i, Name = "Name " + i.ToString(), SomeDecimal = i }); } }}
Reproducible
@using Telerik.Blazor
@using Telerik.Blazor.Components.Grid
<TelerikGrid Data=@GridData
SelectionMode="GridSelectionMode.Multiple"
@bind-SelectedItems="SelectedItems"
Pageable="true"
Height="400px">
<TelerikGridToolBar>
<TelerikGridCommandButton Command="MyDelete" OnClick="DeleteSelectedAsync"
Enabled=@(SelectedItems?.Count() > 0) Icon="delete">Delete</TelerikGridCommandButton>
<TelerikGridCommandButton Enabled="false" OnClick="DeleteSelectedAsync">I must always be disabled</TelerikGridCommandButton>
</TelerikGridToolBar>
<TelerikGridColumns>
<TelerikGridCheckboxColumn />
<TelerikGridColumn Field=@nameof(Employee.Name) />
<TelerikGridColumn Field=@nameof(Employee.Team) Title="Team" />
</TelerikGridColumns>
</TelerikGrid>
@result
@if (SelectedItems != null)
{
<ul>
@foreach (Employee employee in SelectedItems)
{
<li>
@employee.Name
</li>
}
</ul>
}
@code {
void DeleteSelectedAsync()
{
result = $"On {DateTime.Now} there are {SelectedItems?.Count()} items selected";
}
string result;
public List<Employee> GridData { get; set; }
public IEnumerable<Employee> SelectedItems { get; set; }
protected override void OnInitialized()
{
GridData = new List<Employee>();
for (int i = 0; i < 15; i++)
{
GridData.Add(new Employee()
{
EmployeeId = i,
Name = "Employee " + i.ToString(),
Team = "Team " + i % 3
});
}
// select Employee with 3 through 5
SelectedItems = GridData.Skip(2).Take(3).ToList();
}
public class Employee
{
public int EmployeeId { get; set; }
public string Name { get; set; }
public string Team { get; set; }
}
}
You can work around this by disabling virtual scrolling with something like this:
ScrollMode="@(Data.Count() > 30 ? GridScrollMode.Virtual : GridScrollMode.Scrollable)"
Simplest repro code is below - expand a few rows and select items in them, or in the parent grid. I would expect that selection in each grid is independent, but the child grid seems to control the parent selection too, even though it is disabled.
<TelerikGrid Data="salesTeamMembers" PageSize="4" Pageable="true" @bind-SelectedItems="@SelectedItemsMainGrid" SelectionMode="@GridSelectionMode.Single">
<DetailTemplate>
@{
var employee = context as MainModel;
<TelerikGrid Data="employee.Orders" Pageable="true" PageSize="7" SelectionMode="@GridSelectionMode.None">
<GridColumns>
<GridColumn Field="OrderId"></GridColumn>
<GridColumn Field="DealSize"></GridColumn>
</GridColumns>
</TelerikGrid>
}
</DetailTemplate>
<GridColumns>
<GridColumn Field="Id"></GridColumn>
<GridColumn Field="Name"></GridColumn>
</GridColumns>
</TelerikGrid>
@foreach (var item in SelectedItemsMainGrid)
{
<div>@item.Name</div>
}
@code {
List<MainModel> salesTeamMembers { get; set; }
public IEnumerable<MainModel> SelectedItemsMainGrid { get; set; } = Enumerable.Empty<MainModel>();
protected override void OnInitialized()
{
salesTeamMembers = GenerateData();
}
private List<MainModel> GenerateData()
{
List<MainModel> data = new List<MainModel>();
for (int i = 1; i < 16; i++)
{
MainModel mdl = new MainModel { Id = i, Name = $"Name {i}" };
mdl.Orders = Enumerable.Range(1, 15).Select(x => new DetailsModel { OrderId = x, DealSize = x ^ i }).ToList();
data.Add(mdl);
}
return data;
}
public class MainModel
{
public int Id { get; set; }
public string Name { get; set; }
public List<DetailsModel> Orders { get; set; }
}
public class DetailsModel
{
public int OrderId { get; set; }
public double DealSize { get; set; }
}
}
I would like to be able to edit both Date and Time in Grid editing mode.
===
Telerik edit: Possible since version 3.1.0 with through the column EditorType parameter.
Hi there,
currently the grid component does not provide a feature to set a specific position in virtual scrolling mode.
My team has currently implemented a workaround via javascript interop call to set a specific position. The workaround basically calculates the "scroll value" (we reverse engineered this value by looking at the Telerik js code) and passes it to the jQuery scrollTop() function. This results in an update of the scrollbar which in return triggers the OnReadItems event where we fetch the items based on the given skip and take values.
This workaround does not seem to work in all cases and is somewhat unreliable hence i'm requesting an official feature to set a specific position without the javascript hack.
What do you say?
So lonG
Daniel
Reproducible
@page "/"
Reproducible
<TelerikButton OnClick="@(_ => _Splited = !_Splited)">Toggle columns - works fine</TelerikButton>Looking through the examples I can't find one with SelectionMode="GridSelectionMode.Multiple" and using a RowTemplate.
ADMIN EDIT: This is not a bug in the component, an example of how this can be implemented by the app is available in the comments.
I'm not sure what I should be binding my checkbox to so it accurately reflects selection state.
From the RowTemplate Example adding SelectionMode:
<TelerikGrid Data=@GridData
@bind-SelectedItems="@SelectedItems"
SelectionMode="GridSelectionMode.Multiple" Height="@Height">
<RowTemplate Context="product"> @*Trying to inspect what is generated in the examples I came up with this, but not sure what to bind to checked*@
<td role="gridcell" colspan=0 data-col-index="0">
<span>
<input class="k-checkbox k-grid-checkbox telerik-blazor" type="checkbox" />
</span>
</td><td> <img class="rounded-circle" src="@($"images/{product.ProductId}.jpg")" alt="Alternate Text" /> @product.ProductName </td> <td> @(String.Format("{0:C2}", product.UnitPrice)) </td> </RowTemplate> <GridColumns> <GridColumn Field=@nameof(Product.ProductName) Title="Product Name" /> <GridColumn Field=@nameof(Product.UnitPrice) Title="Unit Price" /> </GridColumns> </TelerikGrid>
In the following reproducible, try filtering the third column (SomeNavigationProperty.Field1). It does not work.
<TelerikGrid Data="@myData" Pageable="true" Sortable="true" FilterMode="@GridFilterMode.FilterRow" Groupable="true">row height set in grid definition must apply to all rows in the grid for row virtualization as of now.
in real business case there might be complex content in each row that can't reinforce this - but if each row report its own height, grid still can visualize the load, and it will be much more flexible.