DataGrid: Templates

Templates

For extra customization DataGrid will provide you with two additional templates that you can use to extend it’s default behavior.

A display template is used to customize display cells and an edit template is used to customize cell editors. You can place anything inside of the templates, be it a Blazorise components, regular html tags or your own components.

Both templates have a special context attribute that is used to give access to the underline cell value. To learn more about context please go to official Blazor documentation.

DisplayTemplate

Display template is using TItem as a context value.
Date Of Birth
6/19/1959 | Age: 63
6/9/1968 | Age: 54
12/7/1971 | Age: 51
8/16/1986 | Age: 36
8/9/1958 | Age: 64
<DataGrid TItem="Employee"
          Data="@employeeList"
          Responsive>
    <DataGridNumericColumn Field="@nameof(Employee.DateOfBirth)" Caption="Date Of Birth" Editable>
    <DisplayTemplate>
        @{
            var date = ( context as Employee )?.DateOfBirth;

            if ( date != null )
            {
                @($"{date.Value.ToShortDateString()} | Age: {( DateTime.Now.Year - date.Value.Year )}")
            }
        }
    </DisplayTemplate>
</DataGridNumericColumn>
</DataGrid>
@code{
    [Inject]
    public EmployeeData EmployeeData { get; set; }
    private List<Employee> employeeList;


    protected override async Task OnInitializedAsync()
    {
        employeeList = await EmployeeData.GetDataAsync();
        await base.OnInitializedAsync();
    }
}

EditTemplate

Edit template will give you a way to handle the editing of grid cell values. For this template CellEditContext is used as a context value. Use it to get or set the cell values.
Salary
58 321,87 €
4,00 €
77 090,27 €
54 910,14 €
92 326,27 €
<DataGrid TItem="Employee"
          Data="@employeeList"
          Editable
          Responsive>
    <DataGridCommandColumn />
    <DataGridColumn Field="@nameof(Employee.Salary)" Caption="Salary" DisplayFormat="{0:C}" DisplayFormatProvider="@System.Globalization.CultureInfo.GetCultureInfo("fr-FR")" Editable>
        <EditTemplate>
            <NumericEdit TValue="decimal" Value="@((decimal)context.CellValue)" ValueChanged="@( v => context.CellValue = v)" />
        </EditTemplate>
    </DataGridColumn>
</DataGrid>
@code{
    [Inject]
    public EmployeeData EmployeeData { get; set; }
    private List<Employee> employeeList;

    protected override async Task OnInitializedAsync()
    {
        employeeList = await EmployeeData.GetDataAsync();
        await base.OnInitializedAsync();
    }
}

DetailRowTemplate

DetailRowTemplate allows you to display nested structure bellow each row in the grid. One of the examples is “master-detail” relationship between two data-source inside the DataGrid.

For this template the context value is the item from the parent grid.

Once it’s defined a detail-row will be visible for every row in the grid by default. You may change this behaviour by setting DetailRowStartsVisible to false.

If you want to control the visibility of detail-row you can use DetailRowTrigger attribute that can be defined in it’s parent grid. Once defined, whenever a user clicks a row, the DetailRowTrigger will be evaluated. You may also use the DataGrid API, ToggleDetailRow to programatically trigger the detail-row.

First Name
Kara
Yvette
Pablo
Ernest
Tommy
<DataGrid TItem="Employee"
          Data="@employeeList"
          @bind-SelectedRow="@selectedEmployee"
          DetailRowTrigger="@((e) => e.Item.Salaries?.Count > 0 && e.Item.Id == selectedEmployee?.Id)"
          Responsive>
    <DataGridColumns>
        <DataGridCommandColumn />
        <DataGridColumn Field="@nameof(Employee.FirstName)" Caption="First Name" />
    </DataGridColumns>
    <DetailRowTemplate>
        @{
            var salaries = ( context as Employee ).Salaries;

            <DataGrid TItem="Salary"
                      Data="salaries"
                      Sortable="false"
                      ShowCaptions="false">
                <DataGridCommandColumn />
                <DataGridDateColumn Field="@nameof(Salary.Date)" Caption="Date" />
                <DataGridNumericColumn Field="@nameof(Salary.Total)" Caption="Total" />
            </DataGrid>
        }
    </DetailRowTemplate>
</DataGrid>
@code{
    [Inject]
    public EmployeeData EmployeeData { get; set; }
    private List<Employee> employeeList;
    private Employee selectedEmployee;

    protected override async Task OnInitializedAsync()
    {
        employeeList = await EmployeeData.GetDataAsync();
        await base.OnInitializedAsync();
    }
}

Command Templates

If you want to change the default command buttons, you can use following templates:

  • NewCommandTemplate
  • EditCommandTemplate
  • SaveCommandTemplate
  • CancelCommandTemplate
  • DeleteCommandTemplate
  • ClearFilterCommandTemplate
#First NameLast NameEmailSalary
11KaraBrekkeKara.Brekke@hotmail.com58 321,87 €
12YvetteFerryYvette22@gmail.com4,00 €
13PabloFriesenPablo_Friesen96@gmail.com77 090,27 €
14ErnestHomenickErnest_Homenick92@yahoo.com54 910,14 €
17TommySwaniawskiTommy_Swaniawski@gmail.com92 326,27 €
<DataGrid TItem="Employee"
          Data="@employeeList"
          @bind-SelectedRow="@selectedEmployee"
          Editable
          Responsive>
    <DataGridCommandColumn>
        <NewCommandTemplate>
            <Button Color="Color.Success" Clicked="@context.Clicked">New</Button>
        </NewCommandTemplate>
        <EditCommandTemplate>
            <Button Color="Color.Primary" Clicked="@context.Clicked">Edit</Button>
        </EditCommandTemplate>
    </DataGridCommandColumn>
    <DataGridColumn Field="@nameof(Employee.Id)" Caption="#" Sortable="false" />
    <DataGridColumn Field="@nameof(Employee.FirstName)" Caption="First Name" Editable />
    <DataGridColumn Field="@nameof(Employee.LastName)" Caption="Last Name" Editable />
    <DataGridColumn Field="@nameof(Employee.Email)" Caption="Email" Editable />
    <DataGridColumn Field="@nameof(Employee.Salary)" Caption="Salary" DisplayFormat="{0:C}" DisplayFormatProvider="@System.Globalization.CultureInfo.GetCultureInfo("fr-FR")" Editable>
        <EditTemplate>
            <NumericEdit TValue="decimal" Value="@((decimal)context.CellValue)" ValueChanged="@( v => context.CellValue = v)" />
        </EditTemplate>
    </DataGridColumn>
</DataGrid>
@code{
    [Inject]
    public EmployeeData EmployeeData { get; set; }
    private List<Employee> employeeList;
    private Employee selectedEmployee;

    protected override async Task OnInitializedAsync()
    {
        employeeList = await EmployeeData.GetDataAsync();
        await base.OnInitializedAsync();
    }
}

Loading Templates

If you want to change display of content, while grid is empty or ReadData is executing, you can use following templates:

  • EmptyTemplate
  • LoadingTemplate
#First NameLast NameEmailSalary
No employees were found!
<DataGrid @ref="datagridRef"
          TItem="Employee"
          Data="@employeeList"
          @bind-SelectedRow="@selectedEmployee"
          TotalItems="@totalEmployees"
          ReadData="@LoadEmployeesFromService"
          Responsive>
    <DataGridColumns>
        <DataGridCommandColumn />
        <DataGridColumn Field="@nameof(Employee.Id)" Caption="#" Sortable="false" />
        <DataGridColumn Field="@nameof(Employee.FirstName)" Caption="First Name" Editable />
        <DataGridColumn Field="@nameof(Employee.LastName)" Caption="Last Name" Editable />
        <DataGridColumn Field="@nameof(Employee.Email)" Caption="Email" Editable />
        <DataGridColumn Field="@nameof(Employee.Salary)" Caption="Salary" DisplayFormat="{0:C}" DisplayFormatProvider="@System.Globalization.CultureInfo.GetCultureInfo("fr-FR")" Editable>
            <EditTemplate>
                <NumericEdit TValue="decimal" Value="@((decimal)context.CellValue)" ValueChanged="@( v => context.CellValue = v)" />
            </EditTemplate>
        </DataGridColumn>
    </DataGridColumns>
    <EmptyTemplate>
        <div class="box">
            No employees were found!
        </div>
    </EmptyTemplate>
    <LoadingTemplate>
        <Progress @ref="progressRef" Color="Color.Primary" Max="100" Value="progress" />
    </LoadingTemplate>
</DataGrid>

<Button Background="Background.Primary" Color="Color.Light" Clicked="() => datagridRef.Reload()">Load</Button>
@code{
    protected DataGrid.DataGrid<Employee> datagridRef;
    protected Progress progressRef;
    protected int progress;
    protected Employee selectedEmployee;
    protected int totalEmployees = 0;
    protected List<Employee> employeeList;

    public async Task LoadEmployeesFromService( DataGridReadDataEventArgs<Employee> e )
    {
        /*
        * This can be call to anything like calling an api to load employees.
        * During execution 'LoadingTemplate' will be displayed.
        * If your api call returns empty result, then 'EmptyTemplate' will be displayed,
        * this way you have proper feedback, for when your datagrid is loading or empty.
        */
        progress = 0;
        await InvokeAsync( StateHasChanged );

        await Task.Delay( 500 );
        progress = 25;
        await InvokeAsync( StateHasChanged );

        await Task.Delay( 500 );
        progress = 50;
        await InvokeAsync( StateHasChanged );

        await Task.Delay( 500 );
        progress = 75;
        await InvokeAsync( StateHasChanged );


        await Task.Delay( 500 );
        progress = 100;
        await InvokeAsync( StateHasChanged );
    }
}

ButtonRow Template

Provide a ButtonRowTemplate and have the DataGridCommandMode set to either Default or ButtonRow.

The template has access to the internal commands so you’re also able to construct your own buttons on the pager that can also trigger the Datagrid’s CRUD and clear filter operations as shown in the example below:

#First NameLast NameEmailSalary
11KaraBrekkeKara.Brekke@hotmail.com58 321,87 €
12YvetteFerryYvette22@gmail.com4,00 €
13PabloFriesenPablo_Friesen96@gmail.com77 090,27 €
14ErnestHomenickErnest_Homenick92@yahoo.com54 910,14 €
17TommySwaniawskiTommy_Swaniawski@gmail.com92 326,27 €
1 - 5 of 489 items
489 items
<DataGrid TItem="Employee"
          Data="@employeeList"
          @bind-SelectedRow="@selectedEmployee"
          Editable
          Responsive
          ShowPager
          CommandMode="DataGridCommandMode.ButtonRow">
    <DataGridColumns>
        <DataGridColumn Field="@nameof(Employee.Id)" Caption="#" Sortable="false" />
        <DataGridColumn Field="@nameof(Employee.FirstName)" Caption="First Name" Editable />
        <DataGridColumn Field="@nameof(Employee.LastName)" Caption="Last Name" Editable />
        <DataGridColumn Field="@nameof(Employee.Email)" Caption="Email" Editable />
        <DataGridColumn Field="@nameof(Employee.Salary)" Caption="Salary" DisplayFormat="{0:C}" DisplayFormatProvider="@System.Globalization.CultureInfo.GetCultureInfo("fr-FR")" Editable>
            <EditTemplate>
                <NumericEdit TValue="decimal" Value="@((decimal)context.CellValue)" ValueChanged="@( v => context.CellValue = v)" />
            </EditTemplate>
        </DataGridColumn>
    </DataGridColumns>
    <ButtonRowTemplate>
        <Button Color="Color.Success" Clicked="context.NewCommand.Clicked">New</Button>
        <Button Color="Color.Primary" Disabled="(selectedEmployee is null)" Clicked="context.EditCommand.Clicked">Edit</Button>
        <Button Color="Color.Danger" Disabled="(selectedEmployee is null)" Clicked="context.DeleteCommand.Clicked">Delete</Button>
    </ButtonRowTemplate>
</DataGrid>
@code{
    [Inject]
    public EmployeeData EmployeeData { get; set; }
    private List<Employee> employeeList;
    private Employee selectedEmployee;

    protected override async Task OnInitializedAsync()
    {
        employeeList = await EmployeeData.GetDataAsync();
        await base.OnInitializedAsync();
    }
}