MudBlazor

De Banane Atomic
Aller à la navigationAller à la recherche

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

Razor.svg
<MudIconButton Icon="@Icons.Material.Filled.DeleteForever"
               Size="Size.Small"
               Color="Color.Error"
               aria-label="delete"
               OnClick="@(() => OnDeleteAsync(@context.Id))"
               Href="@($"items/{context.Id}")" />

Menu

Razor.svg
<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>

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);
    };
}

Radio buttons

Razor.svg
<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

Razor.svg
<MudNumericField 
    @bind-Value="item.Quantity"
    Label="Quantity"
    Variant="Variant.Text"
    Min="1"
    HideSpinButtons="true" />

Date picker

Razor.svg
<MudDatePicker Label="Date" @bind-Date="item.Date" DisableToolbar="true" Culture="@frCulture" />

@code {
    CultureInfo frCulture = CultureInfo.GetCultureInfo("fr-FR");
}

Time picker

Razor.svg
<MudTimePicker Label="Time" @bind-Time="item.Time" Culture="@frCulture" />

Autocomplete list

Razor.svg
<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>
Cs.svg
// 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

Razor.svg
<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

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

Bash.svg
# 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

Bash.svg
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/>