Programmatically add columns
I am building a component which inherits the data grid component for common settings etc.. and am looking to create a parameter for specifying whether to show a command column or not and what buttons to have in the command column. I.e. Edit, Delete etc...
What I want to do then do is programmatically check that parameter and if set to true append a column to the list of columns on the grid. This will save me having to always define the command column on every grid, but rather can just set a parameter of say ShowRowEditButton="true".
I have tried to do this via OnAfterRender, OnSetParameters etc.. but am not having any luck.
Do you have any examples of how to achieve this?
|
[Index.razor]
<CommonGrid ShowRowEditButton="false"></CommonGrid> //Command column won’t be shown
|
|
[Counter.razor]
<CommonGrid ShowRowEditButton="true"></CommonGrid> //command column will be shown
|
|
@using Syncfusion.Blazor.Grids
<SfGrid @ref="GridInstance" DataSource="@Orders" AllowPaging="true" Height="315">
<GridEditSettings AllowAdding="true" AllowEditing="true" AllowDeleting="true"></GridEditSettings>
<GridColumns>
. . .
<GridColumn Field=@nameof(Order.Freight) HeaderText="Freight" Format="C2" TextAlign="TextAlign.Right" Width="120"></GridColumn>
@if (ShowRowEditButton)
{
<GridColumn HeaderText="Manage Records" Width="150">
<GridCommandColumns>
<GridCommandColumn Type="CommandButtonType.Edit" ButtonOption="@(new CommandButtonOptions() { IconCss = "e-icons e-edit", CssClass = "e-flat" })"></GridCommandColumn>
<GridCommandColumn Type="CommandButtonType.Delete" ButtonOption="@(new CommandButtonOptions() { IconCss = "e-icons e-delete", CssClass = "e-flat" })"></GridCommandColumn>
. . .
</GridCommandColumns>
</GridColumn>
}
</GridColumns>
</SfGrid>
@code{
SfGrid<Order> GridInstance { get; set; } = new SfGrid<Order>();
[Parameter]
public bool ShowRowEditButton { get; set; }
public List<Order> Orders { get; set; }
. . .
} |
Hi Rahul,
Thanks for the reply. I did however already try what you have suggested above, and while it kind of works what I found is that if you also supply the grid columns on the page, then because the component has a <GridColumns> tag that overrides and all I ended up with was the command column.
How can I have it so that it will still render the <GridColumns> specified on the page / component that is referencing the common grid?
I was trying to do it in code. I.e. onAfterRender or onParametersSet and getting reference to the grids columns and if the ShowRowEditButton was true, dynamically appending a column to the list of grid columns, but that had issues as well.
I.e. in the below case, all you will actually see rendered on the page is the command column.
Page
<CommonGrid ShowRowEditButton="true" DataSource="@DataSource" TValue="@TValue">
<GridColumns>
<GridColumn Field="@FieldName" HeaderText="HeaderText" />
<GridColumn Field="@FieldName" HeaderText="HeaderText" />
</GridColumns>
</CommonGrid>
Component
<sfGrid ...>
<GridColumns>
@if(ShowRowEditButton) {
<GridColumn>
...command column syntax
</GridColumn>
}
</GridColumns>
</sfGrid>
|
[Index.razor]
@using Syncfusion.Blazor.Grids
<CommonGrid ShowRowEditButton="false" Columns="@Columns"></CommonGrid>
@code{
List<GridColumn> Columns = new List<GridColumn>(){
new GridColumn(){ Field = "OrderID", HeaderText = "Order ID", TextAlign = TextAlign.Right,Width = "120"},
new GridColumn(){ Field = "CustomerID", HeaderText = "Customer Name", TextAlign = TextAlign.Center ,Width = "120"}
};
} |
|
[Counter.razor]
@using Syncfusion.Blazor.Grids
<CommonGrid ShowRowEditButton="true" Columns="@Columns"></CommonGrid>
@code{
List<GridColumn> Columns = new List<GridColumn>(){
new GridColumn(){ Field = "Freight", HeaderText = "Freight", TextAlign = TextAlign.Right,Width = "120"},
new GridColumn(){ Field = "ShipCountry", HeaderText = "Ship Country", TextAlign = TextAlign.Center ,Width = "120"}
};
} |
|
|
|
[CommonGrid.razor]
<SfGrid @ref="GridInstance" DataSource="@Orders" AllowPaging="true" Height="315">
<GridEditSettings AllowAdding="true" AllowEditing="true" AllowDeleting="true"></GridEditSettings>
<GridColumns>
@foreach( var cols in Columns)
{
}
@if (ShowRowEditButton)
{
<GridColumn HeaderText="Manage Records" Width="150">
<GridCommandColumns>
<GridCommandColumn Type="CommandButtonType.Edit" ButtonOption="@(new CommandButtonOptions() { IconCss = "e-icons e-edit", CssClass = "e-flat" })"></GridCommandColumn>
. . .
</GridColumn>
}
</GridColumns>
</SfGrid>
@code{
SfGrid<Order> GridInstance { get; set; } = new SfGrid<Order>();
[Parameter]
public bool ShowRowEditButton { get; set; }
public List<Order> Orders { get; set; }
[Parameter]
public List<GridColumn> Columns { get; set; }
. . .
} |
Great thanks.
In the above scenario how would you handle if one of the columns needed to have a template specified?
I was able to get it working another way, but not sure if it is the advisable way (see below)?. Note how I have used @ChildContent in the middle of the grid columns. Then in the page / component referencing the grid I just put in grid columns and it works.
<GridColumns>
@if(ShowCheckboxColumn)
{
<GridColumn Type="ColumnType.CheckBox" Width="50"></GridColumn>
}
@if((ShowRowEditButton || ShowRowDeleteButton) && CommandColumnPosition == CommandColumnPosition.Start)
{
<GridColumn HeaderText="@CommandColumnHeaderText" Width="150" ShowInColumnChooser="false">
<GridCommandColumns>
@if (ShowRowEditButton)
{
<GridCommandColumn Type="CommandButtonType.Edit" ButtonOption="@(new CommandButtonOptions() { IconCss = "e-icons e-edit", CssClass = "e-flat" })"></GridCommandColumn>
}
@if(ShowRowDeleteButton)
{
<GridCommandColumn Type="CommandButtonType.Delete" ButtonOption="@(new CommandButtonOptions() { IconCss = "e-icons e-delete", CssClass = "e-flat" })"></GridCommandColumn>
}
@CustomCommandColumns
</GridCommandColumns>
</GridColumn>
}
@ChildContent
@if((ShowRowEditButton || ShowRowDeleteButton) && CommandColumnPosition == CommandColumnPosition.End)
{
<GridColumn HeaderText="@CommandColumnHeaderText" Width="150" ShowInColumnChooser="false">
<GridCommandColumns>
@if (ShowRowEditButton)
{
<GridCommandColumn Type="CommandButtonType.Edit" ButtonOption="@(new CommandButtonOptions() { IconCss = "e-icons e-edit", CssClass = "e-flat" })"></GridCommandColumn>
}
@if(ShowRowDeleteButton)
{
<GridCommandColumn Type="CommandButtonType.Delete" ButtonOption="@(new CommandButtonOptions() { IconCss = "e-icons e-delete", CssClass = "e-flat" })"></GridCommandColumn>
}
@CustomCommandColumns
</GridCommandColumns>
</GridColumn>
}
</GridColumns>
|
@code{
List<GridColumn> Columns = new List<GridColumn>(){
new GridColumn(){ Field = "OrderID", HeaderText = "Order ID", TextAlign = TextAlign.Right,Width = "120"},
new GridColumn(){ Field = "CustomerID", HeaderText = "Customer Name", TextAlign = TextAlign.Center ,Width = "120"},
new GridColumn(){ HeaderText = "Template Column", Template = g, TextAlign = TextAlign.Right,Width = "120"}
};
static RenderFragment<object> g = (value) =>
{
Order order = value as Order;
return b =>
{
b.AddContent(1,@"name");
};
};
public class Order
{
. . .
}
} |
To programmatically add a command column to a data grid in a derived or wrapper component, you can expose parameters such as ShowRowEditButton or ShowCommandColumn and then conditionally create and append the command column during the grid’s initialization or render phase. Inside the component, check the parameter value and, if it’s true, dynamically add a command column definition (including the desired buttons like Edit or Delete) to the grid’s column collection before the grid is rendered. This way, the base grid logic remains centralized, avoids repetitive column definitions across pages, and allows flexible control over which command buttons appear simply by toggling parameters on the component.
Hi Ali Jaan,
Yes — your approach is correct. You can expose parameters (for example, ShowCommandColumn and ShowRowEditButton) from your derived or wrapper component, and then conditionally add a CommandColumn during the Grid’s render phase.
This below way to base Grid logic centralized and avoids repetitive column definitions across multiple pages, ensuring cleaner and more maintainable code.
Code Snippet:
|
CustomGrid.razor
@using Syncfusion.Blazor.Grids @typeparam TItem
<SfGrid TValue="TItem" @ref="GridRef" DataSource="DataSource" AllowSorting="AllowSorting" AllowPaging="AllowPaging" @attributes="AdditionalAttributes"> <GridPageSettings PageCount="@PAGE_COUNT" PageSize="@DEFAULT_PAGE_SIZE" PageSizes="PageSizes"> </GridPageSettings> @ChildContent </SfGrid>
CustomGrid.razor.cs
public partial class CustomGrid<TItem> : ComponentBase { public const int PAGE_COUNT = 5; public const int DEFAULT_PAGE_SIZE = 10;
[Parameter] public IEnumerable<TItem>? DataSource { get; set; } [Parameter] public bool AllowPaging { get; set; } = true; [Parameter] public bool AllowSorting { get; set; } = true; [Parameter] public string[] PageSizes { get; set; } = new[] { "10", "20", "50" };
[Parameter] public bool ShowRowEditButton { get; set; } = false; [Parameter] public RenderFragment? ChildContent { get; set; }
SfGrid<TItem> GridRef;
// Forwards any additional attributes/events to the inner SfGrid [Parameter(CaptureUnmatchedValues = true)] public IReadOnlyDictionary<string, object>? AdditionalAttributes { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender && ShowRowEditButton) { GridColumn column = new GridColumn { HeaderText = "Edit", Width = "100", TextAlign = TextAlign.Center, Commands = new List<GridCommandColumn> { new GridCommandColumn { ButtonOption=new CommandButtonOptions() { IconCss = "e-icons e-edit", CssClass = "e-flat" }, Type = CommandButtonType.Edit }, new GridCommandColumn { ButtonOption=new CommandButtonOptions() { IconCss = "e-icons e-delete", CssClass = "e-flat" }, Type = CommandButtonType.Delete },
} };
GridRef.Columns.Add(column); await GridRef.RefreshColumnsAsync();
} } }
Index.razor
@using Syncfusion.Blazor.Grids
<CustomGrid DataSource="Orders" TItem="Order" ShowRowEditButton="true"> <GridEditSettings AllowEditing="true"></GridEditSettings> <GridColumns> <GridColumn Field=@nameof(Order.OrderID) IsPrimaryKey="true" HeaderText="Order ID" TextAlign="TextAlign.Right" Width="120"></GridColumn> … </CustomGrid>
@code { public List<Order> Orders { get; set; } = new(); private static readonly Random _random = new Random();
protected override void OnInitialized() { Orders = Enumerable.Range(1, 75).Select(x => new Order() { OrderID = 1000 + x, CustomerID = (new string[] { "ALFKI", "ANANTR", "ANTON", "BLONP", "BOLID" })[_random.Next(5)], Freight = Math.Round(2.1 * x, 2), OrderDate = DateTime.Now.AddDays(-x), }).ToList(); }
public class Order { public int? OrderID { get; set; } public string CustomerID { get; set; } public DateTime? OrderDate { get; set; } public double? Freight { get; set; } } } |
We have attached the relevant sample for your reference. Kindly review it for more information.
Regards,
Sanjay Kumar Suresh
Attachment: Net10GridSupport_e3e81d94.zip
- 7 Replies
- 4 Participants
-
PH Peter Harrison
- Sep 27, 2021 12:16 AM UTC
- Dec 24, 2025 10:04 AM UTC