---
ADMIN EDIT
Here is a workaround - using a bit of JS to clear the checked state of the checkbox element when you clear the SelectedItems collection:
At the end of this post you can find attached a sample project that showcases a more complex scenario where you may want to keep some rows selected but cancel the selection of others (in that sample, only one row with a given ItemType can be selected). It shows how you can get the index in the rendering of a particular row to use for a slightly modified version of the JS function.
@inject IJSRuntime _js
@* Move JavaScript code to a separate JS file in production *@
<script suppress-error="BL9992">
function uncheckGrid() {
var checkboxes = document.querySelectorAll(".no-select .k-grid-checkbox");
for (var i = 0; i < checkboxes.length; i++) {
checkboxes[i].checked = false;
}
}
</script>
<style>
.no-select {
cursor: not-allowed;
}
.no-select .k-checkbox {
pointer-events: none;
}
</style>
<TelerikGrid Data=@GridData
SelectionMode="@GridSelectionMode.Multiple"
SelectedItemsChanged="@((IEnumerable<Employee> employeeList) => OnSelect(employeeList))"
SelectedItems="@SelectedEmployees"
Pageable="true"
Height="400px">
<GridColumns>
<GridCheckboxColumn SelectAll="true" OnCellRender="@OnGridCellRender" />
<GridColumn Field="@nameof(Employee.Name)" />
<GridColumn Field="@nameof(Employee.Team)" />
<GridColumn Field="@nameof(Employee.Active)" />
</GridColumns>
</TelerikGrid>
@if (SelectedEmployees != null)
{
<ul>
@foreach (Employee employee in SelectedEmployees)
{
<li>
@employee.Name
</li>
}
</ul>
}
@code {
private List<Employee> GridData { get; set; } = new List<Employee>();
private IEnumerable<Employee> SelectedEmployees { get; set; } = new List<Employee>();
private void OnGridCellRender(GridCellRenderEventArgs args)
{
var product = (Employee)args.Item;
if (!product.Active)
{
args.Class = "no-select";
}
}
protected void OnSelect(IEnumerable<Employee> newSelected)
{
var validItemsToSelect = newSelected.Where(x => x.Active);
SelectedEmployees = validItemsToSelect;
if (validItemsToSelect.Count() < newSelected.Count())
{
_js.InvokeVoidAsync("uncheckGrid");
}
}
protected override void OnInitialized()
{
for (int i = 1; i <= 7; i++)
{
GridData.Add(new Employee()
{
EmployeeId = i,
Name = $"Employee {i}",
Team = $"Team {i % 3 + 1}",
Active = i % 2 == 0
});
}
}
public class Employee
{
public int EmployeeId { get; set; }
public string Name { get; set; } = string.Empty;
public string Team { get; set; } = string.Empty;
public bool Active { get; set; }
}
}
---
ADMIN EDIT
A sample reproducible is attached.
The issue stems from the inability of the System.Text.Json serializer to work with fields of type "Type" and the filter descriptors have such a field to denote the type of the column. Whether it will be possible for the grid to work around needs to be researched in more detail, because the limitation comes from the framework.
Might be the same problem as the following thread that also offers a few workarounds one can consider: https://feedback.telerik.com/blazor/1505237-set-deserialized-grid-state-in-onstateinit-handler-cause-error-on-open-filter-menu-of-column-on-ui
---
When the Virtualization feature is enabled, triggering Incell edit causes the Grid to scroll. When we scroll the edit is canceled. This happens when the row is partially visible.
https://www.screencast.com/t/zCJ9z9P83c
A more specific case is when you try to edit the last row. In case the editor height is bigger than the row height the Grid tries to scroll but there is no more data. The editor is closed and the item cannot be edited.
https://www.screencast.com/t/331cT4xxt
Reproduction: https://blazorrepl.telerik.com/QxEcECvx22pq4BBG59
When there are wide columns that produce a horizontal scrollbar, scrolling horizontally does not scroll the headers. It must.
WORKAROUND (see also the rules for the containing div that provides the scroll):
<style>
.k-grid,
.k-grid-container,
.k-grid-content.k-virtual-content {
display
: inline-
block
;
}
</style>
REPRODUCIBLE:
@
using
Telerik.Blazor.Components.Grid
<div style=
"width: 1200px; overflow-x: auto; overflow-y:hidden; border: 1px solid red;"
>
<TelerikGrid Data=
"@trades"
EditMode=
"inline"
Pageable=
true
PageSize=10>
<TelerikGridColumns>
<TelerikGridCommandColumn width=
"100"
>
<TelerikGridCommandButton Command=
"Edit"
Icon=
"edit"
>Edit</TelerikGridCommandButton>
<TelerikGridCommandButton Command=
"Update"
Icon=
"save"
ShowInEdit=
"true"
OnClick=
"UpdateItem"
>Update</TelerikGridCommandButton>
<TelerikGridCommandButton Command=
"Cancel"
Icon=
"cancel"
ShowInEdit=
"true"
OnClick=
"CancelItem"
>Cancel</TelerikGridCommandButton>
</TelerikGridCommandColumn>
<TelerikGridColumn Field=
"@(nameof(Trade.TradeId))"
Width=100></TelerikGridColumn>
@*<TelerikGridColumn Field=
"@(nameof(Trade.TradeType))"
Width=200></TelerikGridColumn>*@
<TelerikGridColumn Field=@nameof(Trade.TradeType) Title=
"Trade Type"
>
<EditorTemplate>
@{
var TradeToEdit = context
as
Trade;
if
(TradeToEdit.TradeType ==
"POWER PHYSICAL"
)
{
<select
class
=
"form-control d-inline"
style=
"height: 30px"
onchange=@SaveItem value=@TradeToEdit.TradeType>
<option value=
"POWER PHYSICAL"
>POWER PHYSICAL</option>
<option value=
"GAS PHYSICAL"
> GAS PHYSICAL</option>
</select>
}
else
{
<select
class
=
"form-control d-inline"
style=
"height: 30px"
onchange=@SaveItem value=@TradeToEdit.TradeType>
<option value=
"GAS PHYSICAL"
> GAS PHYSICAL</option>
<option value=
"POWER PHYSICAL"
>POWER PHYSICAL</option>
<option value=
"POWER PHYSICAL"
>POWER FINANCIAL</option>
</select>
}
}
</EditorTemplate>
</TelerikGridColumn>
<TelerikGridColumn Field=
"@(nameof(Trade.Company))"
Width=500></TelerikGridColumn>
<TelerikGridColumn Field=
"@(nameof(Trade.TradeDate))"
Width=500></TelerikGridColumn>
<TelerikGridColumn Field=
"@(nameof(Trade.BegTime))"
Width=500></TelerikGridColumn>
<TelerikGridColumn Field=
"@(nameof(Trade.EndTime))"
Width=500></TelerikGridColumn>
</TelerikGridColumns>
</TelerikGrid>
</div>
@functions {
public
class
Trade
{
public
int
TradeId {
get
;
set
; }
public
string
TradeType {
get
;
set
; }
public
string
Company {
get
;
set
; }
public
DateTime TradeDate {
get
;
set
; }
public
DateTime BegTime {
get
;
set
; }
public
DateTime EndTime {
get
;
set
; }
}
public
List<Trade> trades {
get
;
set
; }
protected
override
void
OnInit()
{
trades =
new
List<Trade>();
for
(
int
i = 0; i < 25; i++)
{
trades.Add(
new
Trade()
{
TradeId = i,
TradeType =
"type "
+ i,
Company =
"company "
+ i,
TradeDate = DateTime.Now.AddDays(i),
BegTime = DateTime.Now.AddHours(-i),
EndTime = DateTime.Now.AddHours(i)
});
}
}
void
SaveItem()
{
}
public
void
UpdateItem(GridCommandEventArgs e)
{
}
public
void
CancelItem(GridCommandEventArgs e)
{
}
}
Steps to reproduce:
1.Create a Telerik Grid with SelectionMode=@GridSelectionMode.Multiple and a GridCheckboxColumn to select/unselect the rows.
Also, bind the selected items to an IEnumerable collection and display the selected items in a <ul>
2.Click on Row1's checkbox - It selects the row, but not checking the checkbox
3.Click on it again- Now it unselects the row, but the checkbox is checked.
4.Click on the SelectAll checkbox in the grid header - It selects all rows, row checkboxes are checked, but the SelectAll checkbox in the grid header remains unchecked.
5.Click on the SelectAll checkbox again - All rows remain selected, row checkboxes remain checked, The SelectAll checkbox is now checked.
6.Click on the SelectAll checkbox again- All rows are unselected, row checkboxes are unchecked, The selectAll checkbox remains checked.
Another issue is, corresponding row checkbox remains checked on moving to next page eventhough the row is not selected.
For eg,
1. a grid of 20 rows displays 10 items per page; Row 2 is selected and checkbox is checked
2. Move to page 2 - Row 12 checkbox is checked (but row 12 is not selected)
Please note that this discrepancy is only when using a checkbox column, otherwise the grid selection using Ctrl + Click works as expected.
Attached Screenshot of one of the issues
On clicking Row 2 checkbox again, result below
Would be helpful to have the feature of copying selected row to the clipboard.
The copy format could be CSV or just tabbed delimiter.
---
ADMIN EDIT
In the meantime, you can consider your own JS-based solution (example StackOverflow thread) and integrate them on a command button in the grid or in the row context menu.
---
Reproducible:
@using System.Collections.ObjectModel;
<div style="align-self:center;text-align:center" class="alert-danger">
@errorMessages
</div>
<div style="align-self:center;text-align:center" class="alert-success">
@successMessages
</div>
<TelerikGrid Data=@entitlementsExtended
Pageable="true"
Groupable="false"
PageSize="@PageSize"
OnUpdate="@UpdateHandler"
Sortable="false"
FilterMode="Telerik.Blazor.GridFilterMode.FilterMenu">
<GridColumns>
<GridColumn Field="@nameof(EntitlementValueDTOExtended.Description)" Editable="false" />
<GridColumn Field=@nameof(EntitlementValueDTOExtended.Value)>
<EditorTemplate>
@{
CurrentlyEditedEntitlement = context as EntitlementValueDTOExtended;
<div>
<TelerikDropDownList Data="@entitlementOptions" @bind-Value="CurrentlyEditedEntitlement.Value" Width="60px" PopupHeight="auto"></TelerikDropDownList>
</div>
}
</EditorTemplate>
</GridColumn>
<GridCommandColumn Width="300px">
<GridCommandButton Command="Save" Icon="save" ShowInEdit="true">Update</GridCommandButton>
<GridCommandButton Command="Edit" Icon="edit">Edit</GridCommandButton>
<GridCommandButton Command="Cancel" Icon="cancel" ShowInEdit="true">Cancel</GridCommandButton>
</GridCommandColumn>
</GridColumns>
</TelerikGrid>
@code {
int PageSize = 10;
public EntitlementValueDTOExtended CurrentlyEditedEntitlement { get; set; } = new EntitlementValueDTOExtended();
//changing this to List<> works
public ObservableCollection<EntitlementValueDTOExtended> entitlementsExtended { get; set; } = new ObservableCollection<EntitlementValueDTOExtended>();
public static List<string> entitlementOptions = new List<string> { "I", "E" };
public string errorMessages { get; set; } = "";
public string successMessages { get; set; } = "";
protected async override Task OnInitializedAsync()
{
IEnumerable<int> entitlements = Enumerable.Range(1, 50);
//this is a simplified workaround for people needing nested models
foreach (var entitlement in entitlements)
{
EntitlementValueDTOExtended entitlementExtended = new EntitlementValueDTOExtended();
entitlementExtended.Id = Guid.NewGuid();
entitlementExtended.Description = $"descr {entitlement}";
entitlementExtended.Value = $"value {entitlement}";
entitlementExtended.EntitlementTypeId = entitlement;
entitlementsExtended.Add(entitlementExtended);
}
StateHasChanged();
await base.OnInitializedAsync();
}
public async Task UpdateHandler(GridCommandEventArgs args)
{
EntitlementValueDTOExtended item = (EntitlementValueDTOExtended)args.Item;
var matchingItem = entitlementsExtended.FirstOrDefault(c => c.Id == item.Id);
if (matchingItem != null)
{
matchingItem.Description = item.Description;
matchingItem.EntitlementTypeId = item.EntitlementTypeId;
matchingItem.Value = item.Value;
}
successMessages = $"updated grid on {DateTime.Now}";
StateHasChanged();
}
public class EntitlementValueDTOExtended
{
public Guid Id { get; set; }
public string Description { get; set; } = "";
public string Value { get; set; } = "";
public int EntitlementTypeId { get; set; } = 0;
}
I would like to export custom data to excel, for example - the selected items.
<AdminEdit>
As an attached file, you can see a sample implementation that shows how you can export the Selected Items from the Grid to excel.
</AdminEdit>
I would like to request a simple update to the Grid component.
When a column width is too small - the column header text is cut-off or is unreadable.
For example:
It would be nice that on mouse hover, the full title would be rendered. Currently to achieve this, I have to implement a custom <HeaderTemplate> for every grid column and add a span myself:
<GridColumn Field="@nameof(SalesOrderLineItem.Quantity)">
<HeaderTemplate>
<span title="Order Quantity">Order Quantity</span>
</HeaderTemplate>
</GridColumn>
Can you update the GridColumn component and add a title attribute to the column <th> element so the browser can show the fill title should the user hover over it?
Hi,
I've noticed some odd behaviour where the OnRead event is being called twice. Initially I thought it was my code, but I've got to a bizarre example where having two Console.WriteLine statements causes the repeated call, but having one doesn't!
In my testing with more code in the method it hasn't been consistent, so I'm not sure if it's a timing/threading issue. I have tested with the following:
My test code looks like this:
@layout EmptyLayout
@page
"/testgrid"
<TelerikGrid Data=@GridData TotalCount=@Total
Pageable=
true
PageSize=15
OnRead=@ReadItems>
<GridColumns>
<GridColumn Field=@nameof(Employee.Id) Title=
"ID"
/>
<GridColumn Field=@nameof(Employee.Name) Title=
"Name"
/>
</GridColumns>
</TelerikGrid>
@code {
public
List<Employee> GridData {
get
;
set
; }
public
int
Total {
get
;
set
; } = 0;
protected
async Task ReadItems(GridReadEventArgs args)
{
Console.WriteLine(
"ReadItems 1"
);
// Remove this line and ReadItems is only called once!!!
Console.WriteLine(
"ReadItems 2"
);
// Adding this makes no difference
//await Task.Delay(1);
}
public
class
DataEnvelope
{
public
List<Employee> CurrentPageData {
get
;
set
; }
public
int
TotalItemCount {
get
;
set
; }
}
public
class
Employee
{
public
int
Id {
get
;
set
; }
public
string
Name {
get
;
set
; }
}
}
Any help appreciated!
Thanks.
An autofit feature would be useful which sizes a column according to fit the current content exactly (with some space on the left and right ;-)
* autofit attribute for a column to automatically autofit the column
* autofit method on a grid column to issue autofit by code
Autofit for entire table (nice to have)
* autofit attribute on the grid element to automatically autofit all its columns (except those explicitely set to AutoFit="false")
* autofit method on a grid to issue autofit by code
I am editing parent and child records in the hierarchy grid. I can edit parent and child records without issue. The only problem I have now is this; when I click edit on a child record, then collapse the parent, the edit of the child record is lost or cancelled but there is no event I can see to use to put things back in non-edit mode.
I enable buttons and links in non-edit (view) mode and disable them when editing a record.
So, is there an event or some way to know the user is collapsing or expanding a parent record?
Thank you,
I want to fetch grid records page per page according to the appropriate filter settings. While this is possible through the OnRead event, I want to be able to send the request to the server so that it is easier to fetch the data, like in the UI for ASP.NET Core grid. Currently you can do this only for a server-side project because you can pass the request object by reference, but for a WASM project it needs to serialize in an HTTP request.
---
ADMIN EDIT
You can find examples of doing this here: https://github.com/telerik/blazor-ui/tree/master/grid/datasourcerequest-on-server
---
The issue can be reproduced using the Filter From Code -> FilterMenu code snippet provided here:
https://docs.telerik.com/blazor-ui/components/grid/filtering#filter-from-code