« MudBlazor » : différence entre les versions
De Banane Atomic
Aller à la navigationAller à la recherche
(→Form) |
(→Menu) |
||
Ligne 78 : | Ligne 78 : | ||
</MudMenuItem> | </MudMenuItem> | ||
</MudMenu> | </MudMenu> | ||
</kode> | |||
== [https://mudblazor.com/components/table Table] == | |||
<kode lang='razor'> | |||
<MudTable | |||
@ref="table" | |||
ServerData="@(new Func<TableState, Task<TableData<MyNamespace.ItemResponse>>>(ServerReloadAsync))" | |||
Hover="true" | |||
Loading="@isSearching" | |||
LoadingProgressColor="Color.Info" | |||
Class="flex-column"> | |||
<ToolBarContent> | |||
<MudFab | |||
Color="Color.Primary" | |||
StartIcon="@Icons.Material.Filled.Add" | |||
Size="Size.Small" | |||
Href="item/new" /> | |||
<MudTextField | |||
T="string" | |||
ValueChanged="@(s => OnSearch(s))" | |||
Placeholder="Search" | |||
Adornment="Adornment.Start" | |||
AdornmentIcon="@Icons.Material.Filled.Search" | |||
IconSize="Size.Medium" | |||
Class="mt-0 mx-16"> | |||
</MudTextField> | |||
</ToolBarContent> | |||
<HeaderContent> | |||
<MudTh>Name</MudTh> | |||
<MudTh></MudTh> | |||
</HeaderContent> | |||
<RowTemplate> | |||
<MudTd DataLabel="Name">@context.Name</MudTd> | |||
<MudTd> | |||
<MudMenu | |||
Icon="@Icons.Material.Filled.MoreVert" | |||
Size="Size.Small" | |||
AnchorOrigin="Origin.CenterLeft" | |||
TransformOrigin="Origin.CenterRight"> | |||
<MudMenuItem> | |||
<MudIconButton | |||
Icon="@Icons.Material.Filled.Edit" | |||
Size="Size.Small" | |||
Color="Color.Primary" | |||
aria-label="edit" | |||
Href="@($"transaction/{context.Id}")" /> | |||
</MudMenuItem> | |||
<MudMenuItem> | |||
<MudIconButton | |||
Icon="@Icons.Material.Filled.DeleteForever" | |||
Size="Size.Small" | |||
Color="Color.Error" | |||
aria-label="delete" | |||
OnClick="@(() => OnDeleteAsync(context.Id))" /> | |||
</MudMenuItem> | |||
</MudMenu> | |||
</MudTd> | |||
</RowTemplate> | |||
<NoRecordsContent> | |||
<MudText>No matching items found</MudText> | |||
</NoRecordsContent> | |||
<LoadingContent> | |||
<MudText>Loading...</MudText> | |||
</LoadingContent> | |||
</MudTable> | |||
</kode> | </kode> | ||
Version du 16 juillet 2023 à 23:01
Links
Components
MessageBox
Pages/MyPage.razor |
<MudButton Variant="Variant.Filled" Color="Color.Error" OnClick="OnDeleteAsync" >Delete</MudButton> <MudMessageBox @ref="deleteItemDialog" Title="Item deletion"> <MessageContent> Are you sure you want to delete the selected item? </MessageContent> <YesButton> <MudButton Variant="Variant.Filled" Color="Color.Error" StartIcon="@Icons.Material.Filled.DeleteForever">Delete</MudButton> </YesButton> </MudMessageBox> |
Pages/MyPage.razor.cs |
private async Task OnDeleteAsync() { var dialogOptions = new DialogOptions { CloseButton = true, DisableBackdropClick = true // modal }; var result = await deleteItemDialog.Show(dialogOptions); if (result != true) { return; } |
SnackBar
Pages/MyPage.razor.cs |
[Inject] private ISnackbar snackbar { get; set; } = default!; snackbar.Add("Success!!!", Severity.Success); snackbar.Add($"Error!!!<br>Error message:<br>{operationStatus.ErrorMessage}", Severity.Error); |
Program.cs |
builder.Services.AddMudServices(config => { config.SnackbarConfiguration.PositionClass = Defaults.Classes.Position.BottomRight; config.SnackbarConfiguration.PreventDuplicates = true; config.SnackbarConfiguration.HideTransitionDuration = 100; }); |
IconButton
<MudIconButton Icon="@Icons.Material.Filled.DeleteForever" Size="Size.Small" Color="Color.Error" aria-label="delete" OnClick="@(() => OnDeleteAsync(@context.Id))" Href="@($"items/{context.Id}")" /> |
Menu
<MudMenu Icon="@Icons.Material.Filled.MoreVert" Size="Size.Small" AnchorOrigin="Origin.CenterLeft" TransformOrigin="Origin.CenterRight"> <MudMenuItem> <MudIconButton Icon="@Icons.Material.Filled.DeleteForever" Size="Size.Small" Color="Color.Error" aria-label="delete" OnClick="@(() => OnDeleteAsync(@context.Id))" /> </MudMenuItem> </MudMenu> |
Table
<MudTable @ref="table" ServerData="@(new Func<TableState, Task<TableData<MyNamespace.ItemResponse>>>(ServerReloadAsync))" Hover="true" Loading="@isSearching" LoadingProgressColor="Color.Info" Class="flex-column"> <ToolBarContent> <MudFab Color="Color.Primary" StartIcon="@Icons.Material.Filled.Add" Size="Size.Small" Href="item/new" /> <MudTextField T="string" ValueChanged="@(s => OnSearch(s))" Placeholder="Search" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0 mx-16"> </MudTextField> </ToolBarContent> <HeaderContent> <MudTh>Name</MudTh> <MudTh></MudTh> </HeaderContent> <RowTemplate> <MudTd DataLabel="Name">@context.Name</MudTd> <MudTd> <MudMenu Icon="@Icons.Material.Filled.MoreVert" Size="Size.Small" AnchorOrigin="Origin.CenterLeft" TransformOrigin="Origin.CenterRight"> <MudMenuItem> <MudIconButton Icon="@Icons.Material.Filled.Edit" Size="Size.Small" Color="Color.Primary" aria-label="edit" Href="@($"transaction/{context.Id}")" /> </MudMenuItem> <MudMenuItem> <MudIconButton Icon="@Icons.Material.Filled.DeleteForever" Size="Size.Small" Color="Color.Error" aria-label="delete" OnClick="@(() => OnDeleteAsync(context.Id))" /> </MudMenuItem> </MudMenu> </MudTd> </RowTemplate> <NoRecordsContent> <MudText>No matching items found</MudText> </NoRecordsContent> <LoadingContent> <MudText>Loading...</MudText> </LoadingContent> </MudTable> |
Form
Pages/EditItem.razor |
<MudCard> <MudForm @ref="@form" Model="@item" Validation="@(itemViewModelValidator.ValidateValue)"> <MudCardContent> <MudTextField @bind-Value="item.Name" For="@(() => item.Name)" Label="Name" /> </MudCardContent> </MudForm> <MudCardActions> <MudButton Variant="Variant.Filled" Color="Color.Primary" Class="ml-auto" OnClick="@(async () => await SubmitAsync())"> Save </MudButton> </MudCardActions> </MudCard> |
Pages/EditItem.razor.cs |
[Inject] private NavigationManager NavigationManager { get; set; } = default!; private MudForm form; private readonly ItemViewModelValidator itemViewModelValidator = new(); private async Task SubmitAsync() { await form.Validate(); if (form.IsValid) { NavigationManager.NavigateTo("transaction"); } } |
Validators/ItemViewModelValidator.cs |
public class ItemViewModelValidator : AbstractValidator<ItemViewModel> { public ItemViewModelValidator() { RuleFor(x => x.Name).NotEmpty(); } public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) => { var result = await ValidateAsync(ValidationContext<TransactionViewModel>.CreateWithOptions( (ItemViewModel)model, x => x.IncludeProperties(propertyName))); return result.IsValid ? (IEnumerable<string>)Array.Empty<string>() : result.Errors.Select(e => e.ErrorMessage); }; } |
Add the package FluentValidation to use it. |
Radio buttons
<MudField Label="Type" Class="mt-2" Variant="Variant.Text" InnerPadding="false"> <MudRadioGroup @bind-SelectedOption="item.Type"> <MudRadio Option="@("type1")" Color="Color.Primary">Type1</MudRadio> <MudRadio Option="@("type2")" Color="Color.Primary">Type2</MudRadio> </MudRadioGroup> </MudField> |
Numeric field
<MudNumericField @bind-Value="item.Quantity" Label="Quantity" Variant="Variant.Text" Min="1" HideSpinButtons="true" /> |
Date picker
<MudDatePicker Label="Date" @bind-Date="item.Date" DisableToolbar="true" Culture="@frCulture" /> @code { CultureInfo frCulture = CultureInfo.GetCultureInfo("fr-FR"); } |
Time picker
<MudTimePicker Label="Time" @bind-Time="item.Time" Culture="@frCulture" /> |
Autocomplete list
<MudAutocomplete T="MyNamespace.CurrencyResponse" Label="Currency" @bind-Value="item.Currency" SearchFuncWithCancel="@SearchCurrenciesByCodeAsync" ToStringFunc="@(x => x == null ? null : x.Code)" Strict="false" ShowProgressIndicator="true"> <BeforeItemsTemplate> <MudText Class="px-4 py-1">3 characters min.</MudText> </BeforeItemsTemplate> <NoItemsTemplate> <MudText Align="Align.Center" Class="px-4 py-1"> No matching currencies found </MudText> </NoItemsTemplate> |
// call to the web API private async Task<IEnumerable<CurrencyResponse>> SearchCurrenciesByCodeAsync(string value, CancellationToken cancellationToken) => await CurrencyClient.GetCurrenciesByCodeAsync(value, cancellationToken); // cache all the currencies private async Task<IEnumerable<CurrencyResponse>> SearchCurrenciesByCodeAsync(string value) { var currencies = await CurrencyClient.GetAllAsync(); // if text is null or empty, show complete list return string.IsNullOrEmpty(value) ? (IEnumerable<CurrencyResponse>)currencies : currencies.Where(x => x.Code.StartsWith(value, StringComparison.InvariantCultureIgnoreCase)); } |
Icons
<MudIconButton Icon="@Icons.Material.Filled.Home" /> <MudIconButton Icon="@myIcon" /> @code { string myIcon = MudBlazor.Icons.Material.Filled.Home; } |
CSS utilities
Spacing
Code | Description |
---|---|
m p | margin padding |
t b r l | top bottom right left |
x | left and right |
y | top and bottom |
a | all 4 sides |
0 1 n1 auto | 0 4px -4px auto |
Border
Code | Description |
---|---|
border | border-width: 1px; |
border-solid | border-style: solid; |
mud-border-primary |
Colors
Theme
Shared/MainLayout.razor |
<MudThemeProvider IsDarkMode="true" Theme="customTheme" /> @code { MudTheme customTheme = new MudTheme { LayoutProperties = new LayoutProperties { DrawerWidthLeft = "160px" // --mud-drawer-width-left 240px } }; } |
Installation
New project
# install MudBlazor templates dotnet new install MudBlazor.Templates # help on new project dotnet new mudblazor --help # new server project named MudBlazor dotnet new mudblazor --host server --output MudBlazor |
Already existing project
dotnet add package MudBlazor |
_Imports.razor |
@using MudBlazor |
Pages/_Host.cshtml |
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet" /> <link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" /> <script src="_content/MudBlazor/MudBlazor.min.js"></script> |
Program.cs |
builder.Services.AddMudServices(); |
Shared/MainLayout.razor |
<MudThemeProvider/> <MudDialogProvider/> <MudSnackbarProvider/> |