I've implemented code that will save the state of the grid columns and reapply that state when the grid renders. If a column is rearranged to a new location it seems to cause a problem with the resizing logic. In my case, I've got a grid with many columns (37). I rearrange a single column. This results in the new column state being saved. (In this example, all I have done is move 1 column from its original position). I then refresh the page. On page initialization, the column state is read and applied to the grid. Next, I resize a single column. (In this example, the first column). The result is that every column between the original location of the moved column and its new location are resized.
What appears to be happening is that somehow the grid saved the columns widths for each column before the resizing and then after the first column was resized, the rest of the columns had their original column widths reapplied but its ignoring the fact the the column state had changed after loading so that the column widths are being applied to the wrong columns. (This feels like an awful explanation and is hard to follow I'm sure). I'm attaching a screenshot of the before/after html that illustrates how the column widths get messed up. Hopefully the visualization will help. The image shows the state of the column widths before and after the first column is resized.
Hi Jeffrey,
I created a test page and played with it, according to your instructions, but could not observe an issue with the column sizes. Here is the page. Can you check it and confirm if the discussed behavior is reproduced with it? If yes, please provide exact step-by-step instructions and I will dive deeper.
=========================
@page "/t1526467"@inject LocalStorage LS
<h3>Ticket 1526467</h3>
<ol>
<li>Reorder column 7 to position 3</li>
<li>Refresh the page</li>
<li>Resize column 1</li>
</ol>
<TelerikButton OnClick="@SaveState">Save State</TelerikButton>
<TelerikButton OnClick="@RestoreState">Restore State</TelerikButton>
<TelerikGrid @ref="@MyGrid"
Data="@Data"
Pageable="true"
PageSize="3"
Sortable="true"
OnStateInit="((GridStateEventArgs<GridItem> args) => OnStateInit(args))"
OnStateChanged="((GridStateEventArgs<GridItem> args) => OnStateChanged(args))"
AutoGenerateColumns="true"
Resizable="true"
Reorderable="true">
<GridColumns>
@{
for (int i = 1; i <= 12; i++)
{
<GridColumn Field="@("Field" + i)" Title="@("Field" + i)" Width="200px" />
}
}
</GridColumns>
</TelerikGrid>
@code {
private List<GridItem> Data { get; set; }
private TelerikGrid<GridItem> MyGrid { get; set; }
private GridState<GridItem> MyGridState { get; set; }
private string LocalStorageKey = "GridState1526467";
private async Task SaveState()
{
MyGridState = MyGrid.GetState();
await LS.SetItem(LocalStorageKey, MyGridState);
}
private async Task RestoreState()
{
await GetGridState();
await MyGrid.SetState(MyGridState);
}
private async Task GetGridState()
{
MyGridState = await LS.GetItem<GridState<GridItem>>(LocalStorageKey);
}
private async Task OnStateInit(GridStateEventArgs<GridItem> args)
{
try
{
await GetGridState();
if (MyGridState != null)
{
args.GridState = MyGridState;
}
}
catch (InvalidOperationException)
{
// the JS Interop for the local storage cannot be used during pre-rendering
}
}
private async Task OnStateChanged(GridStateEventArgs<GridItem> args)
{
await LS.SetItem(LocalStorageKey, args.GridState);
}
protected override async Task OnInitializedAsync()
{
Data = new List<GridItem>();
for (int i = 1; i <= 15; i++)
{
Data.Add(new GridItem()
{
ID = i,
Field1 = "Field1 " + i,
Field2 = "Field2 " + i,
Field3 = "Field3 " + i,
Field4 = "Field4 " + i,
Field5 = "Field5 " + i,
Field6 = "Field6 " + i,
Field7 = "Field7 " + i,
Field8 = "Field8 " + i,
Field9 = "Field9 " + i,
Field10 = "Field10 " + i,
Field11 = "Field11 " + i,
Field12 = "Field12 " + i
});
}
}
public class GridItem
{
public int ID { get; set; }
public string Field1 { get; set; }
public string Field2 { get; set; }
public string Field3 { get; set; }
public string Field4 { get; set; }
public string Field5 { get; set; }
public string Field6 { get; set; }
public string Field7 { get; set; }
public string Field8 { get; set; }
public string Field9 { get; set; }
public string Field10 { get; set; }
public string Field11 { get; set; }
public string Field12 { get; set; }
}
}
=========================
The LocalStorage class implementation is:
=========================
using Microsoft.JSInterop;
using System.Text.Json;
using System.Threading.Tasks;
namespace TelerikBlazorApp
{
public class LocalStorage
{
protected IJSRuntime JSRuntimeInstance { get; set; }
public LocalStorage(IJSRuntime jsRuntime)
{
JSRuntimeInstance = jsRuntime;
}
public ValueTask SetItem(string key, object data)
{
return JSRuntimeInstance.InvokeVoidAsync(
"localStorage.setItem",
new object[] {
key,
JsonSerializer.Serialize(data)
});
}
public async Task<T> GetItem<T>(string key)
{
var data = await JSRuntimeInstance.InvokeAsync<string>("localStorage.getItem", key);
if (!string.IsNullOrEmpty(data))
{
return JsonSerializer.Deserialize<T>(data);
}
return default;
}
public ValueTask RemoveItem(string key)
{
return JSRuntimeInstance.InvokeVoidAsync("localStorage.removeItem", key);
}
}
}
=========================
NOTE: I switched the grid column definitions from 200px to 10rem and the issue goes away.... with that said, my understanding is that there are rending issues with using "rem" and locked columns together...because of that, I have switched to using "px" in my grid definitions.
To recreate the issue with your sample, try these steps:
1. Run project
2. Resize ALL columns..the goal is that none of the columns widths are the same as what's defined in code.
3. Move column 4 to between column 8 and 9.
4. Save the state.
5. Reload the page.
6. Using the developer tools, delete the width in the <table> element.
7. Resize column 4.
You should see one or more of the other columns width adjusted as well.
I realize that I'm asking you to force the issue by removing the width on the <table> but that seems to be the catalyst. It also seems to require that many of the columns widths are different than their default setting in code.... and it seems to require at least one column having been moved. There was one other difference in my project... I have the grid enclosed in a <div> with style="width:calc(100vw - 30px);"
I wouldn't experience this issue at all if the width property were set on the <table> at the time my page renders but for some reason, it's always null on load.
Hopefully this helps.. I really think the key is the width of the <table> element and how it's used in the code that does the column width calculations.
Hi Jeffrey,
I was able to reproduce the problem with the gaps between resized frozen columns. I logged the bug here on your behalf:
https://feedback.telerik.com/blazor/1527048
However, I am still unable to observe the problem with the column resizing itself. The test case with a manually removed table width is not valid, so I hope you will be able to provide a sequence that does not need this step.
On a side note, the initial null width that you see looks weird indeed, and I have notified our developers about it. However, the Grid table often has a null width and that does not cause problems by itself. You can verify this in our online demos.
So the question is - how to reproduce the unexpected multi-column resize in a way that a regular user will experience it? By the way, when you say that several columns change size, do you mean that they resize "gradually" while you drag a single column, or they just snap to a new size and then maintain it? If it is the latter, this may be due to the disappearing gaps between the resized frozen columns. This problem will be fixed when the above logged bug is fixed.