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>
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)
{
}
}
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;
}
By the following steps, the problem occurs:
So, it not possible to navigate through the whole grid with virtualized rows when Navigable=true
@* Scroll the grid instead of paging *@
<TelerikGrid Data=@GridData
ScrollMode="@GridScrollMode.Virtual" Navigable="true"
Height="480px" RowHeight="60" PageSize="20"
Sortable="true" FilterMode="@GridFilterMode.FilterMenu">
<GridColumns>
<GridColumn Field="Id" />
<GridColumn Field="Name" Title="First Name" />
<GridColumn Field="LastName" Title="Last Name" />
<GridColumn Field="HireData" Width="200px">
<Template>
@((context as SampleData).HireDate.ToString("MMMM dd, yyyy"))
</Template>
</GridColumn>
</GridColumns>
</TelerikGrid>
@code {
public List<SampleData> GridData { get; set; }
protected override async Task OnInitializedAsync()
{
GridData = await GetData();
}
private async Task<List<SampleData>> GetData()
{
return Enumerable.Range(1, 1000).Select(x => new SampleData
{
Id = x,
Name = $"name {x}",
LastName = $"Surname {x}",
HireDate = DateTime.Now.Date.AddDays(-x)
}).ToList();
}
public class SampleData
{
public int Id { get; set; }
public string Name { get; set; }
public string LastName { get; set; }
public DateTime HireDate { get; set; }
}
}
https://docs.telerik.com/blazor-ui/components/grid/editing/incell#notes
I am using an EditorTemplate with a method called ChangeHandler(). After clicking in another row everything works fine but if I leave the cell by pressing enter the UpdateHandler gets called more than two times and comparing args.Item with the GridItem doesn't help because the calls are asynchronous.
=====
Admin Edit
With 2.22.0, the InCell editing mode was revamped to provide better user experience and this alters the way it worked. In the common case, there will no longer be double OnUpdate calls (unless explicit application logic invokes them). With 2.23.0, Tab and Enter keys that bubble from editor templates will be handled by the grid like they are handled for the built-in editors.
This means that this issue is, effectively, solved. You can see the Notes section about editor templates to see how you can also handle the OnBlur event to capture mouse clicks outside of the component so that you can save changes and remove the edited item. See the full notes here (the Event Sequence section was heavily revamped for clarity) and here on editor template behavior.
Thus, the previous ides about Save and Cancel methods on the edit context might not be implemented, which will also be one breaking change that we could avoid:
After discussion with the development team, the proposed resolution is to provide a context that provides Save/Cancel operations. The goal is to provide easier configuration for IncellEditing and EditorTemplates and consistent behavior with mouse and keyboard interaction. However, the change will introduce a breaking change in our EditorTemplate, should be researched further and that is why this is logged as a feature request.
=====
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.
Reproducible:
1. Run the snippet below
<TelerikGrid Navigable="true" Pageable="false"
The Custom Filter Menu in the Grid is not working as I would expect.
I am trying to do two things
I am doing something very similar to the demo for the custom filter menu: https://demos.telerik.com/blazor-ui/grid/custom-filter-menu
I have observed that if I set a filter programatically through the grid state, those filters are applied to the grid but are not being passed through the FilterMenuTemplateContext object in the FilterMenuTemplate when I open the Filter Menu for that column. Therefore, I cannot update my custom filter to show which values are currently being filtered on.
Is it by design that the FilterMenuTemplateContext does not contain Filters applied through the grid state or a bug?
---
ADMIN EDIT
As of Dec 2020, there is one outstanding issue - using complex filters (having a CompositeFilterDescriptor) for the FilterRow filter template gets saved in the grid state, but is not loaded as expected - the filter row uses a "regular" FilterDescriptor and cuts off additional descriptors. Thus, the context of the template does not provide all the data from the grid state and you need to extract it manually. I have attached a sample that shows one way of doing that in the StateInit handler.
The FilterMenu already provides all the data in its context and you can bind inputs in the template directly to the filter descriptors. Once the filter row can work with more complex filter descriptors as well, you would be able to create the extra descriptors (if they are not already there) and directly bind the inputs to their value, as opposed to the current approach where view-model fields are used.
---
---
ADMIN EDIT
Attached to this post are a reproducible and a workaround - setting the state in OnAfterRenderAsync with a small delay, so the initial grid render happens, then it can re-render and take the filters into account.
---
Here is the scenario:
In version 2.30 there is no longer need for an explicit blur handler for the in-cell editor template. The editor template closes automatically when the user selects a value from the DropDownList. However, the new value is ignored.
REPL test page: https://blazorrepl.telerik.com/mFbcmQvs16Lf1jwv18
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
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,
When I switch the culture of my App from English to Swedish, the Virtual scrolling feature of the Grid breaks.
===========
ADMIN EDIT
===========
The issue stems from invalid transform style applied to the k-virtual-position div element in Swedish culture. Due to integer to string conversion that takes culture into consideration when setting the style and/or data-translate attribute, when this number is < 0, the negative sign is longer dash for Swedish culture. This longer dash is not parsable by JS and CSS which is why the translateY transform is invalid.
As a workaround for the time being, you can try adding transform style for the k-virtual-position div, so you can override the default one and the correct dash will be applied:
<style>
.k-virtual-position {
transform: translateY(-1080px);
}
</style>
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
---