Hello,
after playing with AI chat integration with telerikgrid, few bumps up shows:
lets have this scenario- request from aichat, to perform some filtering/operations on grid with clumn names like col1,col2,col3... generic.
public async Task<GridAIResponse> GetGridAIData(GridAIRequestDescriptor request)
{
var options = new ChatOptions();
var columnsx = JsonSerializer.Deserialize<List<GridAIColumn>>(JsonSerializer.Serialize(request.Columns));
options.Tools = new List<AITool>();
options.Tools.Clear();
1) //describe the columns or general behavior like "aprox, arround, near"
var ff = ChatOptionsExtensions.GetFilter(columnsx);
ForceSetDescription(ff, @"
If users enters phrases like 'aprox', 'arround', 'near',
operate with field value in between ±10 %.
Example: 'dimensions arround 1000' results in: 'dimension >= 900 AND dimension<= 1100'.
");
options.Tools.Add(ff);
options.Tools.Add(ChatOptionsExtensions.GetSort(columnsx));
ChatResponse completion = await _chatClient.GetResponseAsync(conversationMessages, options);
....
return completion.ExtractGridResponse();
}how to extend "GridAIRequestDescriptor"?
1) - ability to describe column(add). but Description is readonly (coders should add titles or any text manually from column definition - be aware. grid IColumn is accessible only by reflection just now)
OR
2) - ability to specify the "meaninfgull name" (place, where coders can add this)
OR
3)- instead of using just "Fieldname" of the column, use/add the Title(which is more understandable for LLM)
OR
4) field mapping translation layer. GridColumn.Field -> something descriptive and back after fetching response from LLM
fieldnames are mostly "system DB name" and cannot be changed. So FieldName="Column44qty" and Title="qty available stock", you get the point which one tells you more.
new[]
{
new {
Field = "Column44qty",
Title = ""qty available stock",
Type = "number",
Description = "......",
Values = new[] { "x", "yyy", "zzz" }
},...
}
all points 1-4 are not needed, just one of them is ok.
The Telerik UI for Blazor TimePicker currently does not appear to expose an equivalent to the Kendo UI for jQuery TimePicker "focusTime" option.
https://github.com/telerik/kendo-ui-core/blob/master/docs/api/javascript/ui/timepicker.md#focustime-datedefault-null
In Kendo UI for jQuery, focusTime allows the popup to open with a specific time focused without actually setting the selected value. This is useful when the picker has no value yet.
For example, let's say we want the time-picker to open up with the placeholder value of 08:00, how would we achieve this in Telerik UI for Blazor? Currently it defaults the placeholder to the current time.
Thanks
The size of the RadialGauge is not set correctly if changing properties from user input.
@page "/gauge"
<div>
<TelerikCheckBox Id="large" @bind-Value=_large ></TelerikCheckBox>
<label for="large">Large</label>
</div>
<TelerikRadialGauge Width=@(_large ? "500px" : "200px") Height=@(_large ? "500px" : "200px")>
<RadialGaugePointers>
<RadialGaugePointer Value="55" />
</RadialGaugePointers>
</TelerikRadialGauge>
@code {
bool _large;
}Nothing happens with the gauge in the example above, I would expect it to be larger when ticking the checkbox.
If using F12 in the browser I can see that the outer element get the correct size, but not the inner svg...
If user input should control which pointers that are visible as in this example:
@page "/gauge"
<div>
<TelerikCheckBox Id="display_second" @bind-Value=_displaySecond></TelerikCheckBox>
<label for="display_second">Display second pointer</label>
</div>
<TelerikRadialGauge>
<RadialGaugePointers>
<RadialGaugePointer Value="55" />
@if (_displaySecond)
{
<RadialGaugePointer Value="75" Color="red" />
}
</RadialGaugePointers>
</TelerikRadialGauge>
@code {
bool _displaySecond;
}
Environment
Grid ColumnDraggable is never destroyed
In Components/Common/Grid/Rows/TableHeaderRow.cs, Dispose() calls base.Dispose() first, which sets IsDisposed = true. It then calls DestroyColumnDraggable(), which uses InvokeAsync<object>. That method returns early when IsDisposed is true (BaseComponent.InvokeAsync<T>), so destroyColumnDraggable is never sent to the browser. DestroyColumnReorderable() and DestroyColumnResizable() work because they use InvokeVoidAsync, which has no such check.
As a result, every grid with Reorderable="true" or Groupable="true" leaves "<dataId>-telerik-ColumnDraggable" in window.TelerikBlazor._instances. Its draggable.element (the grid's .k-grid-header) keeps the whole disposed page reachable, so the page is never garbage collected.
Object.entries(TelerikBlazor._instances) .filter(([k, i]) => i && i.element && !i.element.isConnected) .map(([k, i]) => k + ' / ' + i.constructor.name)
Sample project attached.
(optional)
one "...-telerik-ColumnDraggable" entry per reorderable or groupable grid, all pointing at detached elements. Each pageA -> pageB round trip adds more, and the detached DOM is never released.
An empty array is returned. Page A's components were disposed, so their JS instances should have been destroyed.
Workaround
After each navigation, we destroy and remove any registered instance whose element is no longer in the page:
const instances = window.TelerikBlazor && window.TelerikBlazor._instances; for (const key of Object.keys(instances || {})) { const i = instances[key]; if (i && i.element && !i.element.isConnected) { try { i.destroy && i.destroy(); } catch (e) { } delete instances[key]; } }
Suggested Fix
(bug report only)
Environment
TabStrip Tab is never destroyed
Components/TabStrip/Tab.razor.cs registers each tab with initTabStripTab in OnAfterRenderAsync. Its Dispose() only releases the DotNetObjectReference; it never calls InvokeDisposeAsync(). The JS Tab.destroy() method is therefore never called, and TabStrip.destroy() does not destroy its child tabs. Every tab stays in window.TelerikBlazor._instances with its detached <li class="k-tabstrip-item">, which again keeps the disposed page reachable.
Object.entries(TelerikBlazor._instances) .filter(([k, i]) => i && i.element && !i.element.isConnected) .map(([k, i]) => k + ' / ' + i.constructor.name)
Sample project attached.
(optional)
One entry per TabStrip tab is returned, all pointing at detached elements. Each pageA -> pageB round trip adds more, and the detached DOM is never released.
An empty array is returned. PageA's components were disposed, so their JS instances should have been destroyed.
Workaround
After each navigation, we destroy and remove any registered instance whose element is no longer in the page:
const instances = window.TelerikBlazor && window.TelerikBlazor._instances; for (const key of Object.keys(instances || {})) { const i = instances[key]; if (i && i.element && !i.element.isConnected) { try { i.destroy && i.destroy(); } catch (e) { } delete instances[key]; } }
Suggested Fix
Please add an OTP Input component to Telerik UI for Blazor. It already exists in Kendo UI for jQuery, Kendo UI for Angular, ASP.NET Core and ASP.NET MVC, but Blazor is missing it.
It’s very common for two-factor authentication and email/SMS code verification. Today we have to build it ourselves with multiple TextBoxes and JS interop.
Main features, similar to the Blazor Bootstrap OTPInput:
@bind-Value and an event when all fields are filledautocomplete="one-time-code"