Hi
Are there any plans on improving the performance on the default export to excel from a Telerik grid using Blazor Wasm?
As seen in this example:
https://docs.telerik.com/blazor-ui/components/grid/export/excel#basics
<TelerikGrid Data="@GridData" Pageable="true" Sortable="true" Resizable="true" Reorderable="true"
FilterMode="@GridFilterMode.FilterRow" Groupable="true" >
<GridToolBarTemplate>
<GridCommandButton Command="ExcelExport" Icon="@SvgIcon.FileExcel">Export to Excel</GridCommandButton>
<label class="k-checkbox-label"><TelerikCheckBox @bind-Value="@ExportAllPages" />Export All Pages</label>
</GridToolBarTemplate>
<GridExport>
<GridExcelExport FileName="telerik-grid-export" AllPages="@ExportAllPages" />
</GridExport>
<GridColumns>
Columns..
</GridColumns>
</TelerikGrid>
At the moment we have about 150 columns and 4000 rows that needs to be exported which takes quite a while.
If not what are your recommendations in speeding up the excel export?
I attempted to develop a versatile grid component for Blazor to facilitate reusability.
@typeparam TItem
<TelerikGrid Data="Data" SelectionMode="GridSelectionMode.Multiple"
Pageable="true" PageSize="3" Page="1"
Sortable="true" SortMode="@SortMode.Multiple"
FilterMode="GridFilterMode.FilterMenu"
EditMode="@GridEditMode.Popup"
Resizable="true" Reorderable="true" ConfirmDelete="true">
<GridSettings>
<GridValidationSettings Enabled="true"></GridValidationSettings>
<GridPopupEditSettings MaxWidth="600px"
MaxHeight="300px"
Class="custom-popup"
Title="Update Details">
</GridPopupEditSettings>
<GridPopupEditFormSettings Orientation="@FormOrientation.Horizontal"
ButtonsLayout="FormButtonsLayout.Center"
Columns="3">
</GridPopupEditFormSettings>
</GridSettings>
<GridToolBarTemplate>
<GridCommandButton Command="ExcelExport" Icon="@SvgIcon.FileCsv">Export to Excel</GridCommandButton>
<GridCommandButton Command="Add" Icon="@SvgIcon.Plus">Add Employee</GridCommandButton>
</GridToolBarTemplate>
<GridExport>
<GridExcelExport FileName="EmployeeDetails Sheet" AllPages="true" />
</GridExport>
<GridColumns>
@GridCols
<GridCommandColumn>
<GridCommandButton Command="Save" Icon="@SvgIcon.Save" ShowInEdit="true">Update</GridCommandButton>
<GridCommandButton Command="Edit" Icon="@SvgIcon.Pencil">Edit</GridCommandButton>
<GridCommandButton Command="Delete" Icon="@SvgIcon.Trash">Delete</GridCommandButton>
<GridCommandButton Command="Cancel" Icon="@SvgIcon.Cancel" ShowInEdit="true">Cancel</GridCommandButton>
</GridCommandColumn>
</GridColumns>
</TelerikGrid>
@code
{
[Parameter]
public IEnumerable<TItem>? Data{get; set;}
[Parameter]
public RenderFragment<TItem>? GridCols { get; set; }
}
@page "/emp"
@inject HttpClient Http
@using System.Text.Json;
<h1>Employee Details</h1>
@if (employees == null)
{
<p><em>Loading...</em></p>
}
else
{
<GenericGrid TItem="EmpDetails" Data="@employees">
<GridCols>
<GridColumn Field="@nameof(EmpDetails.Name)" Title="Employee Name" />
<GridColumn Field="@nameof(EmpDetails.Age)" Title="Age" />
<GridColumn Field="@nameof(EmpDetails.Place)" Title="Place" />
</GridCols>
</GenericGrid>
}
Hello everyone,
I am experiencing an issue with my Blazor application and am seeking advice or solutions from anyone who might have had the same issue.
When interacting with the Telerik Editor within a Telerik Grid, clicking inside the editor unexpectedly exits the edit mode. This seems to be linked to event propagation issues, where clicking the editor triggers a propagation that causes the grid to exit edit mode.
Error Messages:
When my issue triggers, I also see the following error in the console:
Uncaught TypeError: Cannot read properties of null (reading 'state')
This occurs within the telerik-blazor.js script and seems related to handling state changes or events.
I already looked trough Troubleshooting but removing all "StateHasChanged" didn't solve the issue.
What I've Tried:
Implemented JavaScript to stop event propagation using event.stopPropagation() within various event handlers (click, mousedown, etc.).
Checked that the event handlers are correctly assigned and that the JavaScript is initialized at the correct life cycle phase in Blazor (OnAfterRenderAsync).
Removed any redundant StateHasChanged() calls as per Telerik's recommendations to prevent unnecessary re-rendering and potential race conditions.
Code:
The Telerikgrid with the Telerikeditor:
<TelerikGrid Data="ProzessSubPosListe"
EditMode="@GridEditMode.Incell"
OnUpdate="@UpdateHandlerProzessPos"
OnDelete="@DeleteHanlderProzessPos"
Size="@ThemeConstants.Grid.Size.Small"
PageSize="100"
Sortable="true"
Pageable="false"
Resizable="true"
>
<GridColumns>
<GridColumn Field="@nameof(ProzessPosClass.Nr)" Title="Nr" Width="10%"></GridColumn>
<GridColumn Field="@nameof(ProzessPosClass.Title)" Title="Thema" Width="20%"></GridColumn>
<GridColumn Field="@nameof(ProzessPosClass.ProzessContent)" Title="Beschreibung" Width="20%">
<EditorTemplate Context="dataItem">
<div @onclick:stopPropagation="true" @onclick:preventDefault="true">
@{
var item = dataItem as ProzessPosClass;
<TelerikEditor @bind-Value="@item.ProzessContent" Width="650px" Height="400px" ></TelerikEditor>
}
</div>
</EditorTemplate>
</GridColumn>
<GridCommandColumn Context="Journal" Width="100px">
<GridCommandButton Command="Save" Icon="@("save")" ShowInEdit="true"></GridCommandButton>
<GridCommandButton Command="Delete" Icon="@("trash")"></GridCommandButton>
<GridCommandButton Command="Cancel" Icon="@("cancel")" ShowInEdit="true"></GridCommandButton>
</GridCommandColumn>
</GridColumns>
<NoDataTemplate>
<strong>Kein Prozessschritt vorhanden</strong>
</NoDataTemplate>
</TelerikGrid>
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await JSRuntime.InvokeVoidAsync("setupEditorEventHandling");
}
}
My Javascript inside of _Layout.cshtml trying to resolve the issue:
<script>
function setupEditorEventHandling() {
console.log("Setup editor event handling");
document.addEventListener('click', function (event) {
try {
var editor = event.target.closest('.k-editor.telerik-blazor');
if (editor) {
event.stopPropagation();
}
} catch (error) {
console.error('Error handling editor click:', error);
}
}, true);
}
</script>
How the issue looks like:
Has anyone encountered similar issues with event handling in Blazor applications using that setup?
Any insights or suggestions would be greatly appreciated.
<TelerikGrid class="NewPairsGrid"
Data="@Pairs"
AutoGenerateColumns="false"
RowHeight="15"
Height="1000px"
Pageable="true"
PageSize="25"
Sortable="true"
>
<GridColumns>
<GridColumn Field="PairCreatedTimeStamp" Title="Token Age" width="75px">
<Template Context="dataItem">
@if (dataItem is EthPairTradeInfoVDto ethPairTradeInfoVDto)
{
var timestamp = CalculateElapsedTime(dataItem as EthPairTradeInfoVDto);
<span class="tooltip-target">@timestamp</span>
<TelerikTooltip TargetSelector=".tooltip-target" Width="auto" Height="auto" Position="@TooltipPosition.Right">
<Template Context="tooltipContext">
<span>
@RenderTooltipContent(ethPairTradeInfoVDto.PairCreatedTimeStamp)
</span>
</Template>
</TelerikTooltip>
</Template>
</GridColumn>
RenderFragment RenderTooltipContent(DateTime? pairCreatedTimeStamp) =>
builder =>
{
if (pairCreatedTimeStamp.HasValue)
{
builder.OpenElement(0, "span");
builder.AddContent(1, $"Pair Timestamp: {pairCreatedTimeStamp.Value}");
builder.CloseElement();
}
};
Hi guys,
I am fairly new to Blazor/Telerik but trying to get this to work. I introduced OnRead to my code so I can try to capture the grid row count. The problem is when WorkRecord is called it quits refreshing the grid. I have to F5 to see my updates.
Its almost as if OnRead gets in the middle of things and doesn't allow things to complete.
Any idea what I am doing wrong here?
@using Telerik.DataSource.Extensions
@inject DapperRepository<S4PSector4UpdateList> S4GridManager
@inject IJSRuntime js
@if (@S4Records != null && @cpar != null && @cpar.Initialized == true)
{
//FilterMode="@GridFilterMode.FilterRow"
<TelerikGrid
@ref="@GridRef"
OnUpdate=@UpdateItem
Data="@S4Records.ToArray()"
EnableLoaderContainer="true"
OnRead="@OnGridRead"
Pageable="true"
Sortable="true"
Resizable="true"
EditMode="@GridEditMode.Incell"
Size="@ThemeConstants.Grid.Size.Small"
SelectionMode="@GridSelectionMode.Single"
SelectedItems="@SelectedRecord"
ScrollMode="@GridScrollMode.Scrollable">
<GridToolBarTemplate>
<span class="k-toolbar-spacer"></span> @* add this spacer to keep the searchbox on the right *@
<input type="checkbox" id="vehicle1" name="vehicle1" value="Bike">
<label for="vehicle1">Not Started/Assigned</label> 
<input type="checkbox" id="vehicle1" name="vehicle1" value="Bike">
<label for="vehicle1">In Progress</label> 
<input type="checkbox" id="vehicle1" name="vehicle1" value="Bike">
<label for="vehicle1">Update Complete</label> 
<input type="checkbox" id="vehicle1" name="vehicle1" value="Bike">
<label for="vehicle1">Show Only My Records</label> 
<select name="cars" id="cars">
<option value="volvo">100</option>
<option value="saab">50</option>
<option value="opel">20</option>
<option value="audi">10</option>
</select>
<button >Assign Records</button>
<GridCommandButton Command="ExcelExport" Icon="@FontIcon.FileExcel">Export to Excel</GridCommandButton>
<GridSearchBox Width="200px"/>
</GridToolBarTemplate>
<GridColumns>
<GridColumn Field="@nameof(@S4PSector4UpdateList.geid)" Width="75px" Title="GEID" Editable="false" HeaderClass="center-me"/>
<GridColumn Field="@nameof(@S4PSector4UpdateList.soeid)" Width="55px" Title="SOEID" Editable="false" HeaderClass="center-me"/>
<GridCommandColumn Width="45px">
<GridCommandButton Command="WorkRecord" OnClick="@WorkRecord" Size="@ThemeConstants.Button.Size.Small">Work</GridCommandButton>
</GridCommandColumn>
<GridColumn Field="@nameof(S4PSector4UpdateList.primaryfullname)" Width="175px" Title="Full Name" Editable="false" HeaderClass="center-me"/>
<GridColumn Field="@nameof(S4PSector4UpdateList.process_name)" Width="80px" Title="Process Name" Editable="false" HeaderClass="center-me"/>
<GridColumn Field="@nameof(S4PSector4UpdateList.worked_status)" Width="75px" Title="Status" Editable="false" HeaderClass="center-me"/>
<GridColumn Field="@nameof(S4PSector4UpdateList.worked_by_user_soeid)" Width="75px" Title="User SOEID" Editable="false" HeaderClass="center-me"/>
<GridColumn Field="@nameof(S4PSector4UpdateList.worked_by_user_date)" DisplayFormat="{0:MM/dd/yyyy}" Title="Worked Date" Width="85px" Editable="false" HeaderClass="center-me"/>
<GridColumn Field="@nameof(S4PSector4UpdateList.insertdate)" DisplayFormat="{0:MM/dd/yyyy}" Title="Insert Date" Width="85px" Editable="false" HeaderClass="center-me"/>
<GridColumn Field="@nameof(S4PSector4UpdateList.note)" Title="Note" Width="150px" HeaderClass="center-me"/>
<GridColumn Field="@nameof(S4PSector4UpdateList.note_added_by)" Width="80px" Title="Added By" Editable="false" HeaderClass="center-me"/>
<GridColumn Field="@nameof(S4PSector4UpdateList.note_added_date)" DisplayFormat="{0:MM/dd/yyyy}" Title="Note Date" Width="85px" Editable="false" HeaderClass="center-me"/>
<GridColumn Field="@nameof(S4PSector4UpdateList.insertdate)" DisplayFormat="{0:MM/dd/yyyy}" Title="Insert Date" Width="85px" Editable="false" HeaderClass="center-me" />
<GridColumn Field="@nameof(S4PSector4UpdateList.sector_4_eligible_group)" Width="130px" Title="Sector 4 Eligible Group" Editable="false" HeaderClass="center-me"/>
</GridColumns>
</TelerikGrid>
}
@* 👇 Not Visible Components *@
<DisplayAndLogErrorComponent @ref="displayandlogcomponent"></DisplayAndLogErrorComponent>
@code
{
[CascadingParameter(Name = "S4pars")] S4CascadingParameters cpar { get; set; }
[Parameter] public Action Refresh { get; set; }
List<S4PSector4UpdateList> S4Records { get; set; }
public TelerikGrid<S4PSector4UpdateList> GridRef { get; set; }
private DisplayAndLogErrorComponent displayandlogcomponent;
//public S4PSector4UpdateList SelectedRecord { get; set; }
public IEnumerable<S4PSector4UpdateList> SelectedRecord { get; set; } = Enumerable.Empty<S4PSector4UpdateList>();
public int recordcount;
private async Task OnGridRead(GridReadEventArgs args)
{
var result = S4Records.ToDataSourceResult(args.Request);
args.Data = result.Data;
args.Total = result.Total;
recordcount = result.Total;
}
protected override async Task OnInitializedAsync()
{
try
{
if (cpar.Initialized == true)
{
goto finish;
}
cpar.Initialized = true;
goto finish;
finish:;
await LoadAllRecords();
}
catch (Exception ex)
{
displayandlogcomponent.DisplayAndLogError(1, ex, cpar, MethodBase.GetCurrentMethod().DeclaringType.FullName);
}
finally
{
StateHasChanged();
Refresh?.Invoke();
}
}
async Task LoadAllRecords()
{
try
{
await Task.Delay(0);
var result = await S4GridManager.GetAsync("Select * from wta_application.fn_s4_get_active_records() order by id;");
S4Records = result.ToList();
}
catch (Exception ex)
{
displayandlogcomponent.DisplayAndLogError(1, ex, cpar, MethodBase.GetCurrentMethod().DeclaringType.FullName);
}
finally
{
StateHasChanged();
Refresh?.Invoke();
}
}
async Task UpdateItem(GridCommandEventArgs args)
{
try
{
S4PSector4UpdateList item = (S4PSector4UpdateList)args.Item;
var updated = await S4GridManager.UpdateAsync(item);
await LoadAllRecords();
cpar.message = new MessagePars(1, "Record updated successfully!", true);
}
catch (Exception ex)
{
displayandlogcomponent.DisplayAndLogError(1, ex, cpar, MethodBase.GetCurrentMethod().DeclaringType.FullName);
}
finally
{
StateHasChanged();
Refresh?.Invoke();
}
}
private async Task WorkRecord(GridCommandEventArgs args)
{
try
{
var model = args.Item as S4PSector4UpdateList;
//Update Table with user soeid and in progress.
var dictionary = new Dictionary<string, object>
{
{ "@in_soeid", cpar.authuserinfo.soeid },
{ "@in_id", model.id }
};
var parameters = new DynamicParameters(dictionary);
S4GridManager.ExecuteStoredProcedure("wta_application.sp_s4_work_record", parameters);
//Update Count Here
//Copy to clipboard, place success message and select row.
await js.InvokeVoidAsync("navigator.clipboard.writeText", model.soeid.Trim());
cpar.message = new MessagePars(1, model.soeid + " copied to clipboard.", true);
await LoadAllRecords();
//Highlight the row on the grid they selected
SelectedRecord = GridRef.Data.Where(x => x.id == model.id).ToList();
}
catch (Exception ex)
{
displayandlogcomponent.DisplayAndLogError(1, ex, cpar, MethodBase.GetCurrentMethod().DeclaringType.FullName);
}
finally
{
StateHasChanged();
Refresh?.Invoke();
}
}
public void Refreshed()
{
StateHasChanged();
}
}
I'm having trouble with my grid where I am unable to page through my results. I have 200 items in the grid and when I click on any of the buttons on the pager nothing happens. Here is my code
Bonus points if someone can make me understand why my Tooltip isnt working either lol.
<TelerikGrid class="NewPairsGrid"
Data="@Pairs"
AutoGenerateColumns="false"
RowHeight="15"
Height="1000px"
Pageable="true"
PageSize="25"
><GridColumns><GridColumn Title="Pair Info" width="200px"><Template Context="dataItem"><div>
@DisplayTokenImage(dataItem as EthPairTradeInfoVDto)
@($"{(dataItem as EthPairTradeInfoVDto).TokenSymbol} / {(dataItem as EthPairTradeInfoVDto).LpTokenSymbol} - {(dataItem as EthPairTradeInfoVDto).TokenName}")
</div></Template></GridColumn><GridColumn Title="Total Price ETH" width="150px"><Template Context="dataItem"><div>
@FormatPrice(dataItem as EthPairTradeInfoVDto)
</div><div>
@if (dataItem is EthPairTradeInfoVDto ethPairTradeInfoVDto)
{
var UsdPrice = ethPairTradeInfoVDto.CurrentPriceUsd.GetValueOrDefault();
@if (UsdPrice > 0)
{
@($"${UsdPrice} USD")
;
}
else
{
@("Looking for USD Price.../")
;
}
}
</div></Template></GridColumn><GridColumn Field="PairCreatedTimeStamp" Title="Token Age" width="75px"><Template Context="dataItem">
@if (IsLessThanHour(dataItem as EthPairTradeInfoVDto))
{
<i class="fas fa-leaf"></i>
}
@if (dataItem is EthPairTradeInfoVDto ethPairTradeInfoVDto)
{
var timestamp = CalculateElapsedTime(dataItem as EthPairTradeInfoVDto);
<span class="tooltip-target">@timestamp</span><TelerikTooltip TargetSelector=".tooltip-target" Width="250px" Height="150px" Position="@TooltipPosition.Right"><Template Context="ttipContext"><span>
Timestamp: @(ttipContext.DataAttributes)
</span></Template></TelerikTooltip>
}
@* @CalculateElapsedTime(dataItem as EthPairTradeInfoVDto) *@
</Template></GridColumn></GridColumns></TelerikGrid>
I would like to use the ColumnMenu and the FilterRow at the same time. It seems to me that is not possible although it is so obvious !?
I do no need any more filters in the ColumnMenu just the "Columns" Menu-Items to hide/show or lock/unlock columns.
Hi,
In my Blazor grid, I have a column which can have long text in it. I need to use ellipsis on this column e.g put ellipsis after say 50 characters, with the full content then displayed in a tooltip when you hover on the ellipsis.
I know this was possible with your other grids, how can I do this with your blazor grid?
Thanks,