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 the NewRecordGridButton. 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.