Default Data Grid
The <MudDataGrid>
is used to display and work with small amounts of data up to very large datasets, easily and efficiently. In it's
simplest form, the data grid is a just a table, displaying data from a data source.
Nr | Sign | Name | Position | Molar mass |
---|---|---|---|---|
1 | H | Hydrogen | 0 | 1.00794 |
2 | He | Helium | 17 | 4.002602 |
3 | Li | Lithium | 0 | 6.941 |
4 | Be | Beryllium | 1 | 9.012182 |
@using System.Net.Http.Json @using MudBlazor.Examples.Data.Models @inject HttpClient httpClient <MudDataGrid Items="@Elements.Take(4)"> <Columns> <Column T="Element" Field="Number" Title="Nr" /> <Column T="Element" Field="Sign" /> <Column T="Element" Field="Name" /> <Column T="Element" Field="Position" /> <Column T="Element" Field="Molar" Title="Molar mass" /> </Columns> </MudDataGrid>
@code { private IEnumerable<Element> Elements = new List<Element>(); protected override async Task OnInitializedAsync() { Elements = await httpClient.GetFromJsonAsync<List<Element>>("webapi/periodictable"); } }
Advanced Data Grid
In a more advanced scenario, the data grid offers sorting, filtering, pagination and selection. There are two ways to filter the data
fed into the data grid. A QuickFilter
function allows filtering the items in the grid globally. Data can also be filtered by specifying
column filters, enabling a more robust filtration.
In this example, we turn sorting and filtering off for the Nr column using the boolean Sortable
and Filterable
properties
as well as hide the column options icon button by setting the ShowColumnOptions
property to false
. Additionally, we
can override the default SortBy
function for each column, seen in the Name column where we show how you can switch to a sort by the Name's length.
Nr | Sign | Name | Position | Molar mass | Category | |
---|---|---|---|---|---|---|
1 | H | Hydrogen | 0 | 1.00794 | Other | |
2 | He | Helium | 17 | 4.002602 | Noble Gas (p) | |
3 | Li | Lithium | 0 | 6.941 | Alkaline Earth Metal (s) | |
4 | Be | Beryllium | 1 | 9.012182 | Alkaline Metal (s) | |
5 | B | Boron | 12 | 10.811 | Metalloid Boron (p) | |
6 | C | Carbon | 13 | 12.0107 | Nonmetal Carbon (p) | |
7 | N | Nitrogen | 14 | 14.0067 | Nonmetal Pnictogen (p) | |
8 | O | Oxygen | 15 | 15.9994 | Nonmetal Chalcogen (p) | |
9 | F | Fluorine | 16 | 18.998404 | Halogen (p) | |
10 | Ne | Neon | 17 | 20.1797 | Noble Gas (p) | |
@using System.Net.Http.Json @using MudBlazor.Examples.Data.Models @inject HttpClient httpClient <MudDataGrid T="Element" MultiSelection="true" Items="" Sortable="true" Filterable="true" QuickFilter="@_quickFilter" Hideable="true" RowClick="" SelectedItemsChanged=""> <ToolBarContent> <MudText Typo="Typo.h6">Periodic Elements</MudText> <MudSpacer /> <MudTextField @bind-Value="_searchString" Placeholder="Search" Adornment="Adornment.Start" Immediate="true" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"></MudTextField> </ToolBarContent> <Columns> <SelectColumn T="Element" /> <Column T="Element" Field="Number" Title="Nr" Sortable="false" Filterable="false" /> <Column T="Element" Field="Sign" /> <Column T="Element" Field="Name" SortBy="@_sortBy" /> <Column T="Element" Field="Position" /> <Column T="Element" Field="Molar" Title="Molar mass" /> <Column T="Element" Field="Group" Title="Category" /> </Columns> <PagerContent> <MudDataGridPager T="Element" /> </PagerContent> </MudDataGrid> <div class="d-flex flex-wrap mt-4"> <MudSwitch @bind-Checked="@_sortNameByLength" Color="Color.Primary">Sort Name Column By Length</MudSwitch> </div> <MudExpansionPanels Style="flex:1"> <MudExpansionPanel Text="Show Events"> @foreach (var message in _events) { <MudText Typo="@Typo.body2">@message</MudText> } @if(_events.Count > 0) { <div class="d-flex"> <MudSpacer/> <MudButton Class="mt-3" ButtonType="ButtonType.Button" Variant="Variant.Filled" OnClick="@(() => _events.Clear())">Clear</MudButton> </div> } </MudExpansionPanel> </MudExpansionPanels>
@code { private IEnumerable<Element> Elements = new List<Element>(); private string _searchString; private bool _sortNameByLength; private List<string> _events = new(); // custom sort by name length private Func<Element, object> _sortBy => x => { if (_sortNameByLength) return x.Name.Length; else return x.Name; }; // quick filter - filter gobally across multiple columns with the same input private Func<Element, bool> _quickFilter => x => { if (string.IsNullOrWhiteSpace(_searchString)) return true; if (x.Sign.Contains(_searchString, StringComparison.OrdinalIgnoreCase)) return true; if (x.Name.Contains(_searchString, StringComparison.OrdinalIgnoreCase)) return true; if ($"{x.Number} {x.Position} {x.Molar}".Contains(_searchString)) return true; return false; }; protected override async Task OnInitializedAsync() { Elements = await httpClient.GetFromJsonAsync<List<Element>>("webapi/periodictable"); } // events void RowClicked(DataGridRowClickEventArgs<Element> args) { _events.Insert(0, $"Event = RowClick, Index = {args.RowIndex}, Data = {System.Text.Json.JsonSerializer.Serialize(args.Item)}"); } void SelectedItemsChanged(HashSet<Element> items) { _events.Insert(0, $"Event = SelectedItemsChanged, Data = {System.Text.Json.JsonSerializer.Serialize(items)}"); } }
Visual Styling
The <MudDataGrid>
has many built in properties to change its style and also allows for custom styling as well.
Row level classes and styles can be applied using the RowClass
and RowStyle
properties
respectively. To style rows according to the data of the row, you would use the RowClassFunc
and RowStyleFunc
properties. For even finer grain control, you can style at the header, cell and footer level as well by using the CellClass
,
CellStyle
, CellClassFunc
, CellStyleFunc
, etc. properties. However, the header and footer
do not have the Func properties since they are not needed.
Nr | Sign | Name | Position | Molar mass |
---|---|---|---|---|
1 | H | Hydrogen | 0 | 1.00794 |
2 | He | Helium | 17 | 4.002602 |
3 | Li | Lithium | 0 | 6.941 |
4 | Be | Beryllium | 1 | 9.012182 |
@using System.Net.Http.Json @using MudBlazor.Examples.Data.Models @inject HttpClient httpClient <MudDataGrid Items="@Elements.Take(4)" Hover="@_hover" Dense="@_dense" Striped="@_striped" Bordered="@_bordered" RowStyleFunc="@_rowStyleFunc"> <Columns> <Column T="Element" Field="Number" Title="Nr" /> <Column T="Element" Field="Sign" /> <Column T="Element" Field="Name" CellStyleFunc="@_cellStyleFunc" /> <Column T="Element" Field="Position" /> <Column T="Element" Field="Molar" Title="Molar mass" /> </Columns> </MudDataGrid> <div class="d-flex flex-wrap mt-4"> <MudSwitch @bind-Checked="@_hover" Color="Color.Primary">Hover</MudSwitch> <MudSwitch @bind-Checked="@_dense" Color="Color.Secondary">Dense</MudSwitch> <MudSwitch @bind-Checked="@_striped" Color="Color.Tertiary">Striped</MudSwitch> <MudSwitch @bind-Checked="@_bordered" Color="Color.Warning">Bordered</MudSwitch> </div>
@code { private IEnumerable<Element> Elements = new List<Element>(); private bool _hover; private bool _dense; private bool _striped; private bool _bordered; // style the rows where the Element.Position == 0 to have italic text. private Func<Element, int, string> _rowStyleFunc => (x, i) => { if (x.Position == 0) return "font-style:italic"; return ""; }; // style the cells according to the element's physical classification and the molar mass. private Func<Element, string> _cellStyleFunc => x => { string style = ""; if (x.Number == 1) style += "background-color:#8CED8C"; else if (x.Number == 2) style += "background-color:#E5BDE5"; else if (x.Number == 3) style += "background-color:#EACE5D"; else if (x.Number == 4) style += "background-color:#F1F165"; if (x.Molar > 5) style += ";font-weight:bold"; return style; }; protected override async Task OnInitializedAsync() { Elements = await httpClient.GetFromJsonAsync<List<Element>>("webapi/periodictable"); } }
Editing
The <MudDataGrid>
allows editing the data passed into it. Setting the ReadOnly
property
to false
and the EditMode
property to turns editing. There are two different edit modes:
Cell and Form
. Form
displays a form in a popup when editing. Cell
is more like
excel where each cell is ready to edit and as you make edits, they are applied to the data source. To disable editing on a column, set its
IsEditable
property to false
.
By default, the built in editing in the data grid automatically supplies the proper input component for each cell. However, this can be overidden
by supplying an <EditTemplate>
. Inside the template, you have full control over the editing. Take a look at the Position
column below.
Nr | Sign | Name | Position | Molar mass | |
---|---|---|---|---|---|
1 | H | Hydrogen | 0 | 1.00794 | |
2 | He | Helium | 17 | 4.002602 | |
3 | Li | Lithium | 0 | 6.941 | |
4 | Be | Beryllium | 1 | 9.012182 | |
Form
Manual
@using System.Net.Http.Json @using MudBlazor.Examples.Data.Models @inject HttpClient httpClient <MudDataGrid T="Element" Items="@Elements.Take(4)" ReadOnly="@_readOnly" EditMode="@(_isCellEditMode ? DataGridEditMode.Cell : DataGridEditMode.Form)" StartedEditingItem="" CancelledEditingItem="" CommittedItemChanges="" Bordered="true" Dense="true" EditTrigger="@(_editTriggerRowClick ? DataGridEditTrigger.OnRowClick : DataGridEditTrigger.Manual)"> <Columns> <Column T="Element" Field="Number" Title="Nr" IsEditable="false" /> <Column T="Element" Field="Sign" /> <Column T="Element" Field="Name" /> <Column T="Element" Field="Position"> <EditTemplate> <MudSelect @bind-Value="context.Item.Position" Required RequiredError="You must select a Position!!!" Margin="@Margin.Dense"> <MudSelectItem Value="0">zero</MudSelectItem> <MudSelectItem Value="1">one</MudSelectItem> <MudSelectItem Value="17">seventeen</MudSelectItem> </MudSelect> </EditTemplate> </Column> <Column T="Element" Field="Molar" Title="Molar mass" /> <Column T="Element" Hidden="@(_isCellEditMode || _readOnly || _editTriggerRowClick)" CellClass="d-flex justify-end"> <CellTemplate> <MudIconButton Size="@Size.Small" Icon="@Icons.Outlined.Edit" OnClick="@context.Actions.StartEditingItem" /> </CellTemplate> </Column> </Columns> </MudDataGrid> <div class="d-flex flex-wrap mt-4"> <MudSwitch @bind-Checked="@_readOnly" Color="Color.Primary">Read Only</MudSwitch> <div class="d-flex justify-start align-center"> <p class="mud-typography mud-typography-body1 mud-inherit-text mr-2">Form</p> <MudSwitch @bind-Checked="@_isCellEditMode">Cell</MudSwitch> </div> <div class="d-flex justify-start align-center"> <p class="mud-typography mud-typography-body1 mud-inherit-text mr-2">Manual</p> <MudSwitch @bind-Checked="@_editTriggerRowClick">On Row Click</MudSwitch> </div> </div> <MudExpansionPanels Style="flex:1"> <MudExpansionPanel Text="Show Events"> @foreach (var message in _events) { <MudText Typo="@Typo.body2">@message</MudText> } @if(_events.Count > 0) { <div class="d-flex"> <MudSpacer/> <MudButton Class="mt-3" ButtonType="ButtonType.Button" Variant="Variant.Filled" OnClick="@(() => _events.Clear())">Clear</MudButton> </div> } </MudExpansionPanel> </MudExpansionPanels>
@code { private IEnumerable<Element> Elements = new List<Element>(); private bool _readOnly; private bool _isCellEditMode; private List<string> _events = new(); private bool _editTriggerRowClick; protected override async Task OnInitializedAsync() { Elements = await httpClient.GetFromJsonAsync<List<Element>>("webapi/periodictable"); } // events void StartedEditingItem(Element item) { _events.Insert(0, $"Event = StartedEditingItem, Data = {System.Text.Json.JsonSerializer.Serialize(item)}"); } void CancelledEditingItem(Element item) { _events.Insert(0, $"Event = CancelledEditingItem, Data = {System.Text.Json.JsonSerializer.Serialize(item)}"); } void CommittedItemChanges(Element item) { _events.Insert(0, $"Event = CommittedItemChanges, Data = {System.Text.Json.JsonSerializer.Serialize(item)}"); } }
Grouping
The <MudDataGrid>
allows you to group data by column. Setting the Grouping
property
to true
will turn on grouping which will add a menu item in the column options to toggle grouping of that column.
To disable editing on a column, set its IsEditable
property to false
.
Nr | Sign | Name | Position | Molar mass | Category |
---|---|---|---|---|---|
@using System.Net.Http.Json @using MudBlazor.Examples.Data.Models @inject HttpClient httpClient <MudDataGrid @ref="dataGrid" MultiSelection="true" Items="" Sortable="true" Filterable="true" Hideable="true" Groupable="true" GroupExpanded="false"> <ToolBarContent> <MudText Typo="Typo.h6">Periodic Elements</MudText> <MudSpacer /> </ToolBarContent> <Columns> <Column T="Element" Field="Number" Title="Nr" Filterable="false" Groupable="false" /> <Column T="Element" Field="Sign" /> <Column T="Element" Field="Name" /> <Column T="Element" Field="Position" /> <Column T="Element" Field="Molar" Title="Molar mass" /> <Column T="Element" Field="Group" Title="Category" Grouping="true" GroupBy="@_groupBy"> <GroupTemplate> @if (_customizeGroupTemplate) { <span style="font-weight:bold">Group: @context.Grouping.Key <MudChip Variant="Variant.Outlined" Color="Color.Primary" Size="Size.Small">total @context.Grouping.Count()</MudChip></span> } else { <span style="font-weight:bold">Category: @context.Grouping.Key</span> } </GroupTemplate> </Column> </Columns> <PagerContent> <MudDataGridPager T="Element" /> </PagerContent> </MudDataGrid> <div class="d-flex flex-wrap mt-4"> <MudSwitch @bind-Checked="_customizeGroupTemplate" Color="@Color.Primary">Customize Group Template</MudSwitch> <MudSwitch T="bool" Checked="@_customizeGroupBy" Color="@Color.Primary" CheckedChanged="">Customize Group By</MudSwitch> <MudButton OnClick="" Color="@Color.Primary">Expand All</MudButton> <MudButton OnClick="" Color="@Color.Primary">Collapse All</MudButton> </div>
@code { IEnumerable<Element> Elements = new List<Element>(); MudDataGrid<Element> dataGrid; bool _customizeGroupTemplate; static bool _customizeGroupBy; static string[] _nonmetals = new string[] { "H", "He","N", "O", "F", "Ne", "Cl", "Ar", "Kr", "Xe", "Rn", "Br", "C", "P", "Se", "Se", "I" }; Func<Element, object> _groupBy = x => { if (_customizeGroupBy) { if (_nonmetals.Contains(x.Sign)) return "Nonmetal"; return "Metal"; } return x.Group; }; protected override async Task OnInitializedAsync() { Elements = await httpClient.GetFromJsonAsync<List<Element>>("webapi/periodictable"); } void ExpandAllGroups() { dataGrid?.ExpandAllGroups(); } void CollapseAllGroups() { dataGrid?.CollapseAllGroups(); } void CustomizeByGroupChanged(bool isChecked) { _customizeGroupBy = isChecked; dataGrid.GroupItems(); } }
Data Aggregation
The <MudDataGrid>
allows you to aggregate data in several different ways. Data aggregation happens in the
footer of the grid for the most part. By setting an AggregateDefinition
, you can easily add a quick built-in aggregate
or choose to tailor the display to your needs. There are 6 different AggregateTypes
that can be used with the
AggregateDefinition
: Avg, Count, Custom, Max, Min and Sum. For more control over the data aggregation, you can choose the
AggregationType.Custom
and supply your own function which will return a formatted string to display. Lastly, for
complete control over the data aggregation including the look and feel, you use <FooterTemplate>
which has it's
context set to the CurrentPageItems
.
Aggregation is automatically applied to groups when the data grid is grouped by a column. Try it out by grouping the Status column!
Name | Age | Status | Salary | Hired | Manager |
---|---|---|---|---|---|
Sam | 56 | Normal | 50000.00 | 3/5/2005 | False |
Alicia | 54 | Info | 75000.00 | 1/17/2010 | False |
Ira | 27 | Success | 102000.00 | 6/15/2017 | True |
John | 32 | Warning | 132000.00 | 12/23/2021 | True |
Fred | 65 | Warning | 87000.00 | 7/3/2003 | False |
Tabitha | 33 | Info | 157000.00 | 2/12/2015 | True |
Hunter | 22 | Success | 43000.00 | 9/20/2017 | False |
Esme | 55 | Warning | 149000.00 | 8/1/2017 | True |
People:
S am, A licia, I ra, J ohn, F red, T abitha, H unter, E sme | Average age is 43 | Highest: $157,000 | 4 Over $100,000 |
@using System.Net.Http.Json @using MudBlazor.Examples.Data.Models @inject HttpClient httpClient <MudDataGrid Items="@_items" Groupable="true" Filterable="true"> <Columns> <Column T="Model" Field="@nameof(Model.Name)"> <FooterTemplate> @{ int index = 1, count = @context.Items.Count(); } People: @foreach (var person in @context.Items) { <MudAvatar Color="@((Color)index)" Variant="Variant.Outlined" Size="Size.Small" Class="mr-1">@person.Name.First()</MudAvatar>@person.Name.Substring(1) if (index < count) { @(", ") } index++; } </FooterTemplate> </Column> <Column T="Model" Field="@nameof(Model.Age)" AggregateDefinition="_ageAggregation" /> <Column T="Model" Field="@nameof(Model.Status)" ></Column> <Column T="Model" Field="@nameof(Model.Salary)" AggregateDefinition="_salaryAggregation" /> <Column T="Model" Field="HireDate" Title="Hired"> <CellTemplate> @context.Item.HireDate.ToString("d") </CellTemplate> </Column> <Column T="Model" Field="IsManager" Title="Manager" /> </Columns> </MudDataGrid>
@code { public record Model (string Name, int Age, Severity Status, decimal Salary, DateTime HireDate, bool IsManager); IEnumerable<Model> _items = new List<Model>() { new Model("Sam", 56, Severity.Normal, 50_000.00M, new DateTime(2005, 3, 5), false), new Model("Alicia", 54, Severity.Info, 75_000.00M, new DateTime(2010, 1, 17), false), new Model("Ira", 27, Severity.Success, 102_000.00M, new DateTime(2017, 6, 15), true), new Model("John", 32, Severity.Warning, 132_000.00M, new DateTime(2021, 12, 23), true), new Model("Fred", 65, Severity.Warning, 87_000.00M, new DateTime(2003, 7, 3), false), new Model("Tabitha", 33, Severity.Info, 157_000.00M, new DateTime(2015, 2, 12), true), new Model("Hunter", 22, Severity.Success, 43_000.00M, new DateTime(2017, 9, 20), false), new Model("Esme", 55, Severity.Warning, 149_000.00M, new DateTime(2017, 8, 1), true) }; AggregateDefinition<Model> _ageAggregation = new AggregateDefinition<Model> { Type = AggregateType.Avg, DisplayFormat = "Average age is {value}" }; AggregateDefinition<Model> _salaryAggregation = new AggregateDefinition<Model> { Type = AggregateType.Custom, CustomAggregate = x => { var highestSalary = x.Max(z => z.Salary); var countOver100Grand = x.Count(z => z.Salary > 100_000); return $"Highest: {highestSalary.ToString("C0")} | {countOver100Grand} Over {100000:C0}"; } }; }