Grid Buttons
Grid toolbar buttons control how users interact with records in a MainGrid or SubGrid. Buttons are placed inside the Buttons render fragment and automatically appear in the grid's toolbar.
Button Categories
There are three categories of grid buttons based on how they handle record operations:
- Dialog Buttons — Open a form in a dialog to create or edit records inline without leaving the page.
- Navigation Buttons — Navigate to a separate page URL for creating or editing records.
- Action Buttons — Perform operations like deleting, linking, or unlinking records directly.
NewRecordGridButton
Opens a dialog form to create a new record. Requires a TForm type parameter specifying the Razor component to render as the form.
Use Location to control where the dialog appears: DialogLocation.Center (default) or DialogLocation.Right (side panel).
Use FormType to choose between a standard form (FormType.Form) or a multi-step wizard (FormType.WizardForm).
Use Behavior to control when the record is created: GridActionBehavior.Immediately saves to Dataverse right away, while GridActionBehavior.WithGridContext (default) defers the save until the parent context is committed.
<!-- Center dialog with standard form -->
<NewRecordGridButton TForm="NewContactForm" />
<!-- Side panel with standard form -->
<NewRecordGridButton TForm="NewContactForm"
Location="DialogLocation.Right" />
<!-- Center dialog with wizard form -->
<NewRecordGridButton TForm="NewContactForm"
Location="DialogLocation.Center"
FormType="FormType.WizardForm" />
<!-- Save immediately instead of deferring -->
<NewRecordGridButton TForm="NewContactForm"
Behavior="GridActionBehavior.Immediately" />
Standard Form Example
The TForm type parameter specifies a Razor component that defines the form layout. A standard form is simply a Razor component containing editor components. It can include tabs, sections, or any layout you need.
<!-- EditContactForm.razor -->
<FluentTabs Style="width: 100%">
<FluentTab Label="General">
<TextEdit ColumnName="firstname" />
<TextEdit ColumnName="middlename" />
<TextEdit ColumnName="lastname" />
</FluentTab>
<FluentTab Label="Other">
<MoneyEdit ColumnName="annualincome" />
<TextEdit ColumnName="telephone1"
TextFieldType="TextFieldType.Tel" />
</FluentTab>
</FluentTabs>
Wizard Form Example
A wizard form splits the creation process into multiple steps. Define each step using WizardRecordPage components. Use FormType="FormType.WizardForm" on the button to enable wizard mode.
<!-- NewContactForm.razor -->
<WizardRecordPage>
<TextEdit ColumnName="firstname" />
<TextEdit ColumnName="middlename" />
<TextEdit ColumnName="lastname" />
</WizardRecordPage>
<WizardRecordPage>
<MoneyEdit ColumnName="annualincome" />
<TextEdit ColumnName="telephone1"
TextFieldType="TextFieldType.Tel" />
</WizardRecordPage>
Note
When using a wizard form, set
FormType="FormType.WizardForm"on theNewRecordGridButton. The wizard displays Back/Next navigation and validates each page before advancing.
EditRecordGridButton
Opens a dialog form to edit the selected record(s). Like NewRecordGridButton, it requires a TForm type parameter. When multiple records are selected, the form shows shared fields and applies changes to all selected records.
The edit button is automatically triggered when a row is double-clicked in the grid.
<!-- Center dialog (default) -->
<EditRecordGridButton TForm="EditContactForm" />
<!-- Side panel -->
<EditRecordGridButton TForm="EditContactForm"
Location="DialogLocation.Right" />
<!-- Save immediately -->
<EditRecordGridButton TForm="EditContactForm"
Behavior="GridActionBehavior.Immediately" />
NavigateNewRecordGridButton
Navigates to a URL to create a new record. Set the Url parameter to the target page. When used in a SubGrid, the parent record's relationship context is automatically appended as query string parameters.
Use the OnClick callback to dynamically set the URL based on the grid context. This is useful for multi-table grids where the URL depends on the selected view's table.
<!-- Static URL -->
<NavigateNewRecordGridButton Url="/contacts/new" />
<!-- Dynamic URL based on selected view -->
<NavigateNewRecordGridButton OnClick="OnNewClick" />
@code {
private async Task OnNewClick(NavigateGridButtonContext ctx)
{
ctx.Url = ctx.GridContext.SelectedView.TableName switch
{
"contact" => "/contacts/new",
"account" => "/accounts/new",
_ => throw new Exception("Unknown table"),
};
}
}
NavigateEditRecordGridButton
Navigates to a URL to edit the selected record. The Url parameter supports {0} as a placeholder for the selected record's ID.
<!-- {0} is replaced with the selected record's ID -->
<NavigateEditRecordGridButton Url="/contacts/edit?contactId={0}" />
<!-- Dynamic URL -->
<NavigateEditRecordGridButton OnClick="OnEditClick" />
@code {
private async Task OnEditClick(NavigateGridButtonContext ctx)
{
ctx.Url = ctx.GridContext.SelectedView.TableName switch
{
"contact" => "/contacts/edit?contactId={0}",
"account" => "/accounts/edit?accountId={0}",
_ => throw new Exception("Unknown table"),
};
}
}
NavigateRecordGridButton
A general-purpose navigation button with a custom label, icon, and URL. Use this for custom navigation actions that don't fit the new/edit pattern.
<NavigateRecordGridButton Title="View Details"
Url="/records/details?id={0}"
ButtonEnabledBehavior="GridButtonBehavior.WhenOneSelected" />
DeleteRecordGridButton
Deletes the selected records after prompting for confirmation. Use Mode to control whether records are deleted BulkOperationMode.Individually (one by one with progress) or in a single batch.
<!-- Delete one by one with progress -->
<DeleteRecordGridButton Mode="BulkOperationMode.Individually" />
<!-- Delete in a single batch -->
<DeleteRecordGridButton Mode="BulkOperationMode.Batch" />
<!-- Delete immediately without deferring -->
<DeleteRecordGridButton Behavior="GridActionBehavior.Immediately" />
LinkExistingRecordGridButton
Opens a lookup dialog to find and associate existing records via a many-to-many relationship. Only applicable in SubGrid with N:N relationships.
<LinkExistingRecordGridButton />
<!-- Associate immediately -->
<LinkExistingRecordGridButton Behavior="GridActionBehavior.Immediately" />
UnlinkExistingRecordGridButton
Disassociates the selected records from a many-to-many relationship after prompting for confirmation. Only applicable in SubGrid with N:N relationships.
<UnlinkExistingRecordGridButton />
<!-- Disassociate immediately -->
<UnlinkExistingRecordGridButton Behavior="GridActionBehavior.Immediately" />
GridButton
A fully custom button with an OnClick callback that receives the current GridContext. Use this to implement custom toolbar actions.
<SubGrid RelationshipName="contact_customer_accounts">
<Buttons>
<NewRecordGridButton TForm="NewContactForm" />
<EditRecordGridButton TForm="EditContactForm" />
<DeleteRecordGridButton />
<!-- Custom button -->
<GridButton Label="Export"
Icon="@(new Icons.Regular.Size20.ArrowDownload())"
IsButtonEnabled="DefaultGridButtonBehavior.GetBehavior(GridButtonBehavior.WhenOneOrMoreSelected)"
OnClick="OnExportClick" />
</Buttons>
</SubGrid>
@code {
private async Task OnExportClick(GridContext context)
{
var selectedRecords = context.SelectedRecords;
// Custom logic — export, print, send email, etc.
}
}
Common Parameters
Behavior— Controls whether the operation is executed immediately (GridActionBehavior.Immediately) or deferred until the parent context saves (GridActionBehavior.WithGridContext).Mode— For delete/link/unlink buttons, controls whether bulk operations run individually with progress feedback or in a single batch request.IsButtonEnabled/IsButtonVisible— Predicates that control button state based on the current row selection.
