Show Grid Command Column Always Last
Environment
Product | Grid for Blazor |
Description
I define some dynamic Grid columns in a for
or foreach
loop. There is a GridCommandColumn
, which should always appear last, after the other columns.
When I switch the number of dynamic columns or the column definitions, the command column does not stay and the end of the column list.
Steps to Reproduce
- Render a dynamic number of columns inside
<GridColumns>
with a loop. - Hard-code another column after the loop.
- Increase the number of dynamic columns and rebind the Grid.
Static Grid column will reorder when adding more columns
<TelerikRadioGroup Data="@ColumnOptions"
Value="@CurrentColumns"
Layout="@RadioGroupLayout.Horizontal"
OnChange="@( (object newValue) => ChangeGridColumns((int)newValue) )" />
<TelerikGrid TItem="@GridItem" @ref="@GridRef"
OnRead="@OnGridRead">
<GridColumns>
@for (int i = 1; i <= CurrentColumns; i++)
{
<GridColumn Field="Text" Title="@( $"Dynamic column {i}" )" />
}
<GridCommandColumn Title="Static column" Width="200px">
<strong style="color:#f00;">Should be last</strong>
</GridCommandColumn>
</GridColumns>
</TelerikGrid>
@code {
TelerikGrid<GridItem> GridRef { get; set; }
IEnumerable<RadioItem> ColumnOptions { get; set; } = new List<RadioItem>()
{
new RadioItem() { Text = "1 dynamic column", Value = 1 },
new RadioItem() { Text = "2 dynamic columns", Value = 2 }
};
int CurrentColumns { get; set; } = 1;
void ChangeGridColumns(int newValue)
{
CurrentColumns = newValue;
GridRef.Rebind();
}
void OnGridRead(GridReadEventArgs args)
{
args.Data = new List<GridItem>() { new GridItem() { Id = 1, Text = "Text" } };
args.Total = 1;
}
public class GridItem
{
public int Id { get; set; }
public string Text { get; set; }
}
public class RadioItem
{
public int Value { get; set; }
public string Text { get; set; }
}
}
Cause\Possible Cause(s)
Unexpected reordering of dynamic components is related to how Blazor works. The framework appends newly added components at the end of the component collection.
Typical scenarios that can exhibit such column position change are binding to DataTable
or another dynamic datasource.
Solution
To make a specific Grid column appear always last:
- Set the
@key
directive of all columns to a unique value. This will help the Blazor framework distinguish the columns and their client-side rendering. - (optional) Define the "static" column together with all "dynamic" columns inside a single loop.
Static Grid column will remain last when adding new columns
<TelerikRadioGroup Data="@ColumnOptions"
Value="@CurrentColumns"
Layout="@RadioGroupLayout.Horizontal"
OnChange="@( (object newValue) => ChangeGridColumns((int)newValue) )" />
<TelerikGrid TItem="@GridItem" @ref="@GridRef"
OnRead="@OnGridRead">
<GridColumns>
@for (int i = 1; i <= CurrentColumns; i++)
{
<GridColumn Field="Text" Title="@( $"Dynamic column {i}" )" @key="@i" />
}
<GridCommandColumn Title="Static column" Width="200px" @key="@(CurrentColumns + 1)">
<strong style="color:#f00;">Should be last</strong>
</GridCommandColumn>
</GridColumns>
</TelerikGrid>
@code {
TelerikGrid<GridItem> GridRef { get; set; }
IEnumerable<RadioItem> ColumnOptions { get; set; } = new List<RadioItem>()
{
new RadioItem() { Text = "1 dynamic column", Value = 1 },
new RadioItem() { Text = "2 dynamic columns", Value = 2 }
};
int CurrentColumns { get; set; } = 1;
void ChangeGridColumns(int newValue)
{
CurrentColumns = newValue;
GridRef.Rebind();
}
void OnGridRead(GridReadEventArgs args)
{
args.Data = new List<GridItem>() { new GridItem() { Id = 1, Text = "Text" } };
args.Total = 1;
}
public class GridItem
{
public int Id { get; set; }
public string Text { get; set; }
}
public class RadioItem
{
public int Value { get; set; }
public string Text { get; set; }
}
}