In my opinion the documentation for MudDataGrid is a bit lacking when it comes to loading paged data from a dynamic source such as an API.
ServerData
attribute?Page
and PageSize
of the GridState
object?Let's say you want to make a blazor page that has a list of animals on it, displayed in a MudDataGrid. The animal data will come from an API.
ServerData
attribute?Firstly, define DTOs to handle the user's request, and the response from the API:
public class GridDataRequestDto
{
public int Page { get; set; } = 0; // The page number for the data we're requesting
public int PageSize { get; set; } = 10; // The number of items per page
}
public class AnimalListDto
{
public List<AnimalListItemDto> Items { get; set; } = new();
public int ItemTotalCount { get; set; } = 0; // The total count of items before paging
}
public class AnimalListItemDto
{
public Guid Id { get; set; }
public string Name { get; set; }
}
This, then, is the implementation of your MudDataGrid component in your blazor page:
<MudDataGrid ServerData="LoadGridData"
T="AnimalListItemDto" @ref="_dataGrid">
<Columns>
<PropertyColumn Property="@(item => item.Name)" Title="Animal" />
</Columns>
<PagerContent>
<MudDataGridPager T="AnimalListItemDto" />
</PagerContent>
</MudDataGrid>
As you can see, the Grid's ServerData
attribute is set to call a method called LoadGridData
. We define that in our blazor page code:
private MudDataGrid<AnimalListItemDto>? _dataGrid;
private GridDataRequestDto _requestDto = new();
private async Task<GridData<AnimalListItemDto>> LoadGridData(GridState<AnimalListItemDto> state)
{
_requestDto.Page = state.Page;
_requestDto.PageSize = state.PageSize;
AnimalListDto apiResponse = await GetAnimalList(_requestDto);
GridData<AnimalListItemDto> data = new()
{
Items = apiResponse.Items,
TotalItems = apiResponse.ItemTotalCount
};
return data;
}
You need to create the GetAnimalList()
method that performs the API call, so on the server you would do your DB query and return a AnimalListDto
result with the Items
and ItemTotalCount
properties populated.
After you've done that, congratulations! You have successfully implemented ServerData
in MudDataGrid.
Say you want the user to view an animal when they click on a MudDataGrid row. Also you want to put a button on each row to allow the user to edit the animal if they click it.
Let's modify the MudDataGrid implementation in the blazor page code a little:
<MudDataGrid ServerData="LoadGridData" T="AnimalListItemDto"
RowClick="OnRowClick" Hover="true" @ref="_dataGrid">
<Columns>
<PropertyColumn Property="@(item => item.Name)" Title="Animal" />
<TemplateColumn>
<CellTemplate>
<button @onclick="() => EditItem(context.Item!)" @onclick:stopPropagation>Edit</button>
</CellTemplate>
</TemplateColumn>
</Columns>
<PagerContent>
<MudDataGridPager T="AnimalListItemDto" />
</PagerContent>
</MudDataGrid>
So now we have to implement a couple of new methods in our code:
private async Task OnRowClick(DataGridRowClickEventArgs<AnimalListItemDto> args)
{
YourViewMethod(args.Item);
}
private void EditItem(AnimalListItemDto item)
{
YourEditMethod(item);
}
Now we want the user to be able to search the Animal data, by putting keywords into a search box.
Firstly we need to add a SearchTerm property to our request DTO:
public class GridDataRequestDto
{
public string? SearchTerm { get; set; } = null;
public int Page { get; set; } = 0; // The page number for the data we're requesting
public int PageSize { get; set; } = 10; // The number of items per page
}
Then, we add a form to the Blazor page, above the grid:
<EditForm Model="_requestDto" OnValidSubmit="Search">
<InputText placeholder="e.g. Animal Name" @bind-Value="_requestDto.SearchTerm" />
<button type="submit">Search</button>
</EditForm>
Now we add the Search
method:
private async Task Search()
{
if (_dataGrid is not null)
{
await _dataGrid!.ReloadServerData();
}
}
Now the SearchTerm
property is naturally sent along to the API call. You just need to modify your DB query to handle it.
Page
and PageSize
of the GridState
object?This might be a niche requirement, but you might want to use persisted state to pre-set the data grid to load a different page of data to the default. You might want to do this if the user has left the page, and then returned, expecting the data to be on the page where they left it.
Firstly, you need to load the state into the request DTO. So, you need to implement a state manager, e.g. an instance of type GridDataRequestDto
called AnimalListState
that you inject into your page by adding a scoped MyStateHelper
service to your Program.cs builder.Services
. Then in your blazor page code:
@inject IMyStateHelper MyStateHelper;
protected override async Task OnParametersSetAsync()
{
_requestDto = MyStateHelper.AnimalListState;
}
That way, the request DTO has been pre-populated when it comes to render time. So the final step is to to tell the DataGrid to pre-set the Page and PageSize. MudBlazor haven't given us a very nice way to do it, but I find that this approach works:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender && _dataGrid?.HasPager == true)
{
_dataGrid!.CurrentPage = _requestDto.Page;
await _dataGrid.SetRowsPerPageAsync(_requestDto.PageSize);
}
}
That's all folks. Please let me know if you have any problems.