Hello,
new version has broken "dynamic" changing column properties/visiblity runtime, especially- selection mode and causing lot of "rerendering".
Video attachment:
1 - first part is OLD version(prior 4.1.0) 4.0.1
2 - seccond part(after changing next browser tab) is new version 4.1.0
SAME setup
Iam already using hint for blazor with IDs of columns, found in Your documentation...etc. @key="@("sIDX")"
.....
-->>Clicking on Button for changing grid mode and visibility of columns**
<TelerikToggleButton Title="Oznaceni vice radku" Icon="@FontIcon.ListUnordered" OnClick="@( _ =>{ CurrentStackItem.gSelectionMode=(CurrentStackItem.gSelectionMode==GridSelectionMode.Multiple)?GridSelectionMode.Single:GridSelectionMode.Multiple;CurrentStackItem.gSelectedItems = Enumerable.Empty<ExpandoObject>();})"
Selected="@(CurrentStackItem.gSelectionMode==GridSelectionMode.Multiple)"></TelerikToggleButton>
....
<GridColumns>
-->>First "static" 2 columns**
<GridCheckboxColumn Visible=@(CurrentStackItem.gSelectionMode==GridSelectionMode.Multiple) @key="@("sIDX")" Width="70px" Locked="true" SelectAll="true" SelectAllMode="GridSelectAllMode.Current"></GridCheckboxColumn><GridColumn FieldType=@typeof(bool) Visible=@(IsPicker==true || (XSmall==false && CurrentStackItem.gSelectionMode==GridSelectionMode.Single )) @key="@("sCMD")" Filterable="false" Sortable="false" Locked="true" Width="@((IsPicker==true && XSmall==true)?"45px":"120px")">
<HeaderTemplate> </HeaderTemplate><Template Context="ctx"><div @onclick:preventDefault="true" @onclick:stopPropagation="true">
-->> THIS part is hitting LOT OF TIME in debug (expected is at best only once)
@{if (XSmall==false)
{
-->> here is LOT OF dynamic buttons.
}
</div></Template></GridColumn>
-->> rest of the dynamic columns. In video, starting with "ciiislo org" in header
@if (GridDef.ColStore != null && GridDef.ColStore.Any())
{
foreach (var it in GridDef.ColStore.Where(x => x.Verejny == true))
{
<GridColumn @key=@it.FldName Field=@it.FldName FieldType=@it.FldType Title=@it.VerejnyNazev ShowFilterCellButtons="false" Width=@it.cSirkaSestava
TextAlign=@it.cZarovnani
><FooterTemplate>
@if (it.Sumovat == true)
{
@context.Sum
}
</FooterTemplate></GridColumn>
}
}
</GridColumns>
Feel free to change the Subject.
Thanks, have a nice day
Currently, the empty cells in the exported Excel file contain zero-length strings. As a result, the ISBLANK() function returns false for them while the cells essentially do not have content.
Please allow the empty Grid cells to be treated as blank in the exported Excel file.
===
ADMIN EDIT
===
For the time being, you may extend the formula to also check whether the length of the cell content is 0. For that purpose, you may use the LEN() function as suggested here: https://learn.microsoft.com/en-us/office/troubleshoot/excel/isblank-function-return-false#workaround.
Grid with columns price1 and price2. Enter value in price1, switch to price2, enter value there, and editor is set to old value after async events finish.
The value entered in price2 is correctly set to the property, but the editor reverts to the previous value. If you escape edit mode of the cell, the value entered before the events finish will be shown.
On (fast) tabbing and entering values, this removes the first values entered before the async background events finish.
I tried reproducing the problem in REPL, but could not get the exact same behaviour. In our case no specific value is being set to price2, it just reverts.
https://blazorrepl.telerik.com/cxEzvQvE52q8aaAi27
How would you approach preventing the editor from being overridden by other cells' delayed events?
Here is a runnable REPL test page. A possible workaround is to render the Grid only if it has columns:
@{
if (GridColumns.Count() > 0)
{
<TelerikGrid Data="@Data">
<GridColumns>
@foreach (var column in GridColumns)
{
<GridColumn Field="@column.DataField"
ShowColumnMenu="false" Title="@column.DisplayName" Resizable="true" Width="500px">
<FooterTemplate>
foo
</FooterTemplate>
</GridColumn>
}
</GridColumns>
</TelerikGrid>
}
}
Scenario #1
I want my users to confirm the update of a cell value with the built-in Confirmation Dialog for Blazor. If I use the keyboard (Enter, Tab) to close the edit the Confirmation dialog will popup, but after closing it the Grid hangs.
Scenario #2
If I edit a cell and press enter very quickly, the grid is not able to get the new value inserted after confirming it through the dialog.
Scenario #3
If you press Enter very quickly to confirm the value for deletion, the value is not always removed.
Are there any plans to have the datagrid be both groupable and draggable?
Thanks,
Andy
Hello
What is the purpose of this (https://docs.telerik.com/blazor-ui/components/grid/selection/overview#row-drag-and-drop);
If the user drags selected rows, the current row selection will be cleared on row drop.
Is this a bug? As when you select multiple rows, then drag and drop the rows, it clears the bound selectedItems object (but the rows still remain ticked in the UI). Just confirming this is something that will be fixed?
Cheers
Phil
I am binding a Grid to a collection of ExpandoObjects. In the collection, there are decimal values. When I try to add Aggregates for the decimal values the Grid throws an exception.
<AdminEdit>
As a workaround, you can cast the decimal values to double instead.
</AdminEdit>
Hello,
I'm having issues trying to figure out how to change values (from the model) when I'm Incell Mode without triggers the OnRead events after. The actual code is working great since I was able to remove the Incell mode on the OnChangeModel event below, but OnRead is keeps call after (which I didn't need and slow user experience)
Is there a way to cancel the OnRead ?
<TelerikGrid OnRead="ReadItems" EditMode="GridEditMode.Incell"
@ref="@GridRef">
<GridColumns>
<GridEditDropDownColumn Field="Test1" Data="@Eval?.ListEvaluationTypes" Title="Title" Width="130px" OnChange="OnChangeModel" />
</GridColumns>
</TelerikGrid>
private TelerikGrid<EvaluationListDTO> GridRef { get; set; }
protected async Task OnChangeModel(object model)
{
var item = (EvaluationListDTO)model;
var state = GridRef?.GetState();
//Save in the Database
// use the state to remove the edited item (close the editor)
state.EditItem = null;
state.OriginalEditItem = null;
await GridRef.SetStateAsync(state);
}
===ADMIN EDIT===
Currently, we use groups for calculating all aggregates in Grid. We can optimize the process so that when there are no groups, specific aggregates are still calculated.
The Blazor TelerikGrid component should support a dropdown column. It should be exactly the same as the dropdown column in the Ajax grid.
https://docs.telerik.com/devtools/aspnet-ajax/controls/grid/columns/column-types#dropdown
It would be nice if I could specify an item in the inline editor (or any other for that matter) to get focus when the editor is activated.
Thanks,
Kenny
===
Telerik edit:
A possible workaround is:
The example below also shows how to enter Grid edit mode programmatically and how to focus a specific field when editing with OnRowClick.
<TelerikGrid @ref="@GridInlineRef"
Data="@GridInlineData"
EditMode="@GridEditMode.Inline"
OnAdd="@OnGridAddEdit"
OnEdit="@OnGridAddEdit"
OnCreate="@OnGridInlineCreate"
OnUpdate="@OnGridInlineUpdate"
OnRowClick="@OnGridRowClick">
<GridToolBarTemplate>
<GridCommandButton Command="Add">Add</GridCommandButton>
</GridToolBarTemplate>
<GridColumns>
<GridColumn Field="@nameof(Product.Name)">
<EditorTemplate>
@{ var editItem = (Product)context; }
<TelerikTextBox @ref="@NameTextBoxRef" @bind-Value="@editItem.Name" DebounceDelay="0" />
</EditorTemplate>
</GridColumn>
<GridColumn Field="@nameof(Product.Price)">
<EditorTemplate>
@{ var editItem = (Product)context; }
<TelerikNumericTextBox @ref="@PriceNumericTextBoxRef" @bind-Value="@editItem.Price" DebounceDelay="0" />
</EditorTemplate>
</GridColumn>
<GridColumn Field="@nameof(Product.Stock)">
<EditorTemplate>
@{ var editItem = (Product)context; }
<TelerikNumericTextBox @ref="@StockNumericTextBoxRef" @bind-Value="@editItem.Stock" DebounceDelay="0" />
</EditorTemplate>
</GridColumn>
<GridCommandColumn>
<GridCommandButton Command="Edit">Edit</GridCommandButton>
<GridCommandButton Command="Save" ShowInEdit="true">Update</GridCommandButton>
<GridCommandButton Command="Cancel" ShowInEdit="true">Cancel</GridCommandButton>
</GridCommandColumn>
</GridColumns>
</TelerikGrid>
@code {
private TelerikGrid<Product>? GridInlineRef { get; set; }
private TelerikTextBox? NameTextBoxRef { get; set; }
private TelerikNumericTextBox<decimal?>? PriceNumericTextBoxRef { get; set; }
private TelerikNumericTextBox<int>? StockNumericTextBoxRef { get; set; }
private string EditFieldToFocus { get; set; } = string.Empty;
private List<Product> GridInlineData { get; set; } = new List<Product>();
private void OnGridAddEdit(GridCommandEventArgs args)
{
EditFieldToFocus = nameof(Product.Stock);
}
private async Task OnGridRowClick(GridRowClickEventArgs args)
{
EditFieldToFocus = args.Field;
var itemToEdit = (Product)args.Item;
args.ShouldRender = true;
if (GridInlineRef != null)
{
var gridState = GridInlineRef.GetState();
gridState.InsertedItem = null!;
gridState.OriginalEditItem = itemToEdit;
gridState.EditItem = itemToEdit.Clone();
await GridInlineRef.SetStateAsync(gridState);
}
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!string.IsNullOrEmpty(EditFieldToFocus))
{
await Task.Delay(200);
switch (EditFieldToFocus)
{
case nameof(Product.Name):
if (NameTextBoxRef != null)
{
await NameTextBoxRef.FocusAsync();
}
break;
case nameof(Product.Price):
if (PriceNumericTextBoxRef != null)
{
await PriceNumericTextBoxRef.FocusAsync();
}
break;
case nameof(Product.Stock):
if (StockNumericTextBoxRef != null)
{
await StockNumericTextBoxRef.FocusAsync();
}
break;
default:
break;
}
EditFieldToFocus = string.Empty;
}
}
#region Programmatic Inline Editing
private async Task InlineAdd()
{
var gridState = GridInlineRef!.GetState();
gridState.InsertedItem = new Product();
gridState.InsertedItem.Name = "New value";
gridState.OriginalEditItem = null!;
gridState.EditItem = null!;
await GridInlineRef.SetStateAsync(gridState);
}
private async Task InlineEdit()
{
if (GridInlineData.Any())
{
var gridState = GridInlineRef!.GetState();
gridState.InsertedItem = null!;
gridState.OriginalEditItem = GridInlineData.First();
gridState.EditItem = GridInlineData.First().Clone();
gridState.EditItem.Name = "Updated inline value";
EditFieldToFocus = nameof(Product.Price);
await GridInlineRef.SetStateAsync(gridState);
}
}
private async Task InlineCancel()
{
var gridState = GridInlineRef!.GetState();
gridState.InsertedItem = null!;
gridState.OriginalEditItem = null!;
gridState.EditItem = null!;
await GridInlineRef.SetStateAsync(gridState);
}
private async Task InlineUpdate()
{
var gridState = GridInlineRef!.GetState();
if (gridState.EditItem != null)
{
OnGridInlineUpdate(new GridCommandEventArgs()
{
Item = gridState.EditItem
});
}
else if (gridState.InsertedItem != null)
{
OnGridInlineCreate(new GridCommandEventArgs()
{
Item = gridState.InsertedItem
});
}
gridState.InsertedItem = null!;
gridState.OriginalEditItem = null!;
gridState.EditItem = null!;
await GridInlineRef.SetStateAsync(gridState);
}
#endregion Programmatic Inline Editing
#region Grid Inline Editing Handlers
private void OnGridInlineUpdate(GridCommandEventArgs args)
{
var updatedItem = (Product)args.Item;
var index = GridInlineData.FindIndex(i => i.Id == updatedItem.Id);
if (index != -1)
{
GridInlineData[index] = updatedItem;
}
}
private void OnGridInlineCreate(GridCommandEventArgs args)
{
var createdItem = (Product)args.Item;
createdItem.Id = Guid.NewGuid();
GridInlineData.Insert(0, createdItem);
}
#endregion Grid Inline Editing Handlers
#region Data Generation and Model
protected override void OnInitialized()
{
for (int i = 1; i <= 3; i++)
{
GridInlineData.Add(new Product()
{
Id = Guid.NewGuid(),
Name = $"Product {i}",
Price = Random.Shared.Next(1, 100) * 1.23m,
Stock = (short)Random.Shared.Next(0, 1000)
});
}
}
public class Product
{
public Guid Id { get; set; }
public string Name { get; set; } = string.Empty;
public decimal? Price { get; set; }
public int Stock { get; set; }
public DateTime ReleaseDate { get; set; }
public bool InProduction { get; set; }
public Product Clone()
{
return new Product()
{
Id = Id,
Name = Name,
Price = Price,
Stock = Stock,
ReleaseDate = ReleaseDate,
InProduction = InProduction
};
}
}
#endregion Data Generation and Model
}