Masking

Input masking allows conforming user input to a specific format while typing.

PatternMask

<MudTextField> can be configured to apply rules to the user input by setting its Mask property. The easiest to use Mask is the PatternMask which allows you to specify the input structure with a simple pattern consisting of pre-defined mask characters.

In this example the mask string is "0000 0000 0000 0000" prompting for blocks of digits and refusing invalid input. Note how the cursor automatically jumps over delimiters so you don't have to type them. You can also try pasting the test credit card number 4543474002249996.

Credit Card Number:
Expiration Date:
CVC:
<MudGrid Class="justify-space-between" Style="max-width: 400px;">
    <MudItem xs="12">
        <MudTextField Mask="@(new PatternMask("0000 0000 0000 0000"))" Label="Credit Card Number" 
                      @bind-Value="creditCard"  Variant="@Variant.Text" Clearable />
    </MudItem>
    <MudItem xs="4">
        <MudTextField Mask="@(new DateMask("MM/YY", 'Y', 'M'))" Label="Expires" 
                      @bind-Value="expiration"  Variant="@Variant.Text" />
    </MudItem>
    <MudItem xs="4"/>
    <MudItem xs="4">
        <MudTextField Mask="@(new PatternMask("000"))" Label="CVC" 
                      @bind-Value="cvc"  Variant="@Variant.Text" />
    </MudItem>
    <MudItem xs="12">
        Credit Card Number: <b>@creditCard</b><br/>
        Expiration Date: <b>@expiration</b><br/>
        CVC: <b>@cvc</b>
    </MudItem>
</MudGrid>
@code {
    private string creditCard;
    private string expiration;
    private string cvc;
}
Defining Mask Characters

When you use PatternMask without setting its MaskChars property, you can use the default masking characters a, 0 and *. See their definitions below. But you are not limited to these. You can re-define them or define your own.

Placeholder Description Regex
a Letters, lower- and upper-case, both ASCII and Unicode \p{L}
0 Digits 0-9 \d
* Letters (Unicode) or digits \p{L}|\d

Note: undefined mask characters are automatically treated as delimiters.
The example below defines its own MaskChars. It also shows the features Placeholder which makes the user aware of the input format and CleanDelimiters which removes delimiters from the resulting Value. Last but not least the second mask also transforms all lower-case input into upper-case. You can also try pasting dc12aa309c23 into the field.

##:##:##:##:##:##
XX-XX-XX-XX-XX-XX
MAC Address:
Cleaned MAC Address:
<MudGrid Class="justify-space-between" Style="max-width: 800px;">
    <MudItem xs="12" sm="6">
        <MudTextField Mask="@mask1" Label="MAC Address"  HelperText="@mask1.Mask"
                      @bind-Value="mac1"  Variant="@Variant.Text" Clearable />
    </MudItem>
    <MudItem xs="12" sm="6">
        <MudTextField Mask="@mask2" Label="MAC with Placeholder" HelperText="@mask2.Mask"
                      @bind-Value="mac2"  Variant="@Variant.Text" Clearable />
    </MudItem>
    <MudItem xs="12" sm="6">
        MAC Address: <b>@mac1</b>
    </MudItem>
    <MudItem xs="12" sm="6">
        Cleaned MAC Address: <b>@mac2</b>
    </MudItem>
</MudGrid>
@code {
    public string mac1, mac2;

    public PatternMask mask1 = new PatternMask("##:##:##:##:##:##") { 
        MaskChars = new[] { new MaskChar('#', @"[0-9a-fA-F]") } 
    };

    public PatternMask mask2 = new PatternMask("XX-XX-XX-XX-XX-XX") { 
        MaskChars = new[] { new MaskChar('X', @"[0-9a-fA-F]") },
        Placeholder = '_',
        CleanDelimiters = true,
        Transformation = AllUpperCase
    };
    
    // transform lower-case chars into upper-case chars
    private static char AllUpperCase(char c) => c.ToString().ToUpperInvariant()[0];

}
MultiMask

MultiMask is a powerful masking algorithm which can change its pattern depending on partial input. It uses the same MaskChars as PatternMask. Check out the example code to see how easy it is to set up.

Credit Card:
American Express: starts with 34/37
34·· ······ ·····
Diners Club: starts with 300-305/309
300· ······ ···
JCB: starts with 35/2131/1800
35·· ···· ···· ····
VISA: starts with 4
4··· ···· ···· ····
MasterCard: starts with 51-55/22-27
51·· ···· ···· ····
Discover: starts with 6011/65/644-649
6011 ···· ···· ····

Example inspired by Cleave.js

@using MudBlazor.Interfaces

<MudGrid Class="justify-space-between mb-3 mx-n3" Style="max-width: 800px;">
    <MudItem xs="12">
        <MudTextField Mask="@mask" Label="Credit Card Number" Style="max-width: 400px;"
                  @bind-Value="cardNumber" Variant="@Variant.Text" Clearable/>
    </MudItem>
    <MudItem xs="12">
        Credit Card: <b>@cardNumber</b>
    </MudItem>
</MudGrid>
@code {
    string cardNumber, cardType;

    MultiMask mask = new MultiMask("0000 0000 0000 0000",
        new MaskOption("American Express", "0000 000000 00000", @"^(34|37)"),
        new MaskOption("Diners Club", "0000 000000 0000", @"^(30[0-59])"),
        new MaskOption("JCB", "0000 0000 0000 0000", @"^(35|2131|1800)"),
        new MaskOption("VISA", "0000 0000 0000 0000", @"^4"),
        new MaskOption("MasterCard", "0000 0000 0000 0000", @"^(5[1-5]|2[2-7])"),
        new MaskOption("Discover", "0000 0000 0000 0000", @"^(6011|65|64[4-9])")
    );
    MaskOption? option = null;
    Dictionary<string, Variant> variants = new();
    MudElement element;

    protected override void OnInitialized()
    {
        base.OnInitialized();
        mask.OptionDetected += (o, input) =>
        {
            option = o;
            cardType = o == null ? "Unknown" : o.Value.Id;
            UpdateClasses();
            // re-render only MudElement's children
            (element as IMudStateHasChanged)?.StateHasChanged();
        };
        UpdateClasses();
    }

    void UpdateClasses()
    {
        foreach (var type in new[] { "American Express", "Diners Club", "JCB", "VISA", "MasterCard", "Discover" })
            variants[type] = type == cardType ? Variant.Filled : Variant.Outlined;
    }
}

@* Note: MudElement is used here to limit the render-update to this html tree  *@
<MudElement HtmlTag="div" @ref="element" Style="max-width: 800px;" Class="mud-width-full">
    <MudGrid Class="justify-space-between">
        <MudItem xs="12" sm="6">
            <MudAlert Variant="@variants["American Express"]" NoIcon Dense Class="mb-2">
                American Express: starts with 34/37<br/>
                <pre>34&#183;&#183; &#183;&#183;&#183;&#183;&#183;&#183; &#183;&#183;&#183;&#183;&#183;</pre>
            </MudAlert>
            <MudAlert Variant="@variants["Diners Club"]" NoIcon Dense Class="mb-2">
                Diners Club: starts with 300-305/309<br/>
                <pre>300&#183; &#183;&#183;&#183;&#183;&#183;&#183; &#183;&#183;&#183;</pre>
            </MudAlert>
            <MudAlert Variant="@variants["JCB"]" NoIcon Dense Class="mb-2">
                JCB: starts with 35/2131/1800<br/>
                <pre>35&#183;&#183; &#183;&#183;&#183;&#183; &#183;&#183;&#183;&#183; &#183;&#183;&#183;&#183;</pre>
            </MudAlert>
        </MudItem>
        <MudItem xs="12" sm="6">
            <MudAlert Variant="@variants["VISA"]" NoIcon Dense Class="mb-2">
                VISA: starts with 4<br/>
                <pre>4&#183;&#183;&#183; &#183;&#183;&#183;&#183; &#183;&#183;&#183;&#183; &#183;&#183;&#183;&#183;</pre>
            </MudAlert>
            <MudAlert Variant="@variants["MasterCard"]" NoIcon Dense Class="mb-2">
                MasterCard: starts with 51-55/22-27<br/>
                <pre>51&#183;&#183; &#183;&#183;&#183;&#183; &#183;&#183;&#183;&#183; &#183;&#183;&#183;&#183;</pre>
            </MudAlert>
            <MudAlert Variant="@variants["Discover"]" NoIcon Dense Class="mb-2">
                Discover: starts with 6011/65/644-649<br/>
                <pre>6011 &#183;&#183;&#183;&#183; &#183;&#183;&#183;&#183; &#183;&#183;&#183;&#183;</pre>
            </MudAlert>
        </MudItem>
    </MudGrid>
    <MudText Class="mud-text-secondary" Typo="Typo.body2">Example inspired by Cleave.js</MudText>
</MudElement>
DateMask

DateMask is an auto-correcting calendar-aware date input mask with customizable format. There are some restrictions though. Day and month must be dual digit blocks like dd and MM. The year can either be denoted by yy or by yyyy. The characters for the day, month and year blocks are customizable. You can align the three blocks in any order and add any delimiters you want or none at all. The day block can be left out. Year and month blocks must be used or yields undefined results as will multiple usage of a block.

yyyy-MM-dd
ISO:
MM/dd/yyyy
US:
TT.MM.JJJJ
AT:
MM/YY
MM/YY:
@using System.Globalization


<MudGrid Class="justify-space-between" Style="max-width: 800px;">
    <MudItem  xs="12" sm="6">
        <MudTextField Mask="@mask1" Label="ISO Date"  HelperText="@mask1.Mask"
                      @bind-Value="isoDate"  Variant="@Variant.Text" Clearable />
        ISO: <b>@isoDate</b>
    </MudItem>
    <MudItem  xs="12" sm="6">
        <MudTextField Mask="@mask2" Label="US" HelperText="@mask2.Mask"
                      @bind-Value="usDate"  Variant="@Variant.Text" Clearable />
        US: <b>@usDate</b>
    </MudItem>
    <MudItem  xs="12" sm="6">
        <MudTextField Mask="@mask3" Label="AT"  HelperText="@mask3.Mask"
                      @bind-Value="atDate"  Variant="@Variant.Text" Clearable />
        AT: <b>@atDate</b>
    </MudItem>
    <MudItem  xs="12" sm="6">
        <MudTextField Mask="@mask4" Label="Month" HelperText="@mask4.Mask"
                      @bind-Value="monthAndYear"  Variant="@Variant.Text" Clearable />
        MM/YY: <b>@monthAndYear</b>
    </MudItem>
</MudGrid>
@code {
    string isoDate, usDate, atDate;
    string monthAndYear;

    IMask mask1 = new DateMask("yyyy-MM-dd");
    IMask mask2 = new DateMask("MM/dd/yyyy");
    IMask mask3 = new DateMask("TT.MM.JJJJ", 'J', 'M', 'T');
    IMask mask4 = new DateMask("MM/YY", 'Y', 'M');
}
RegexMask

RegexMask is very different from the other algorithms, because it does not use mask characters. Instead it lets you define the allowed input with a single C# regular expression. The advantage of RegexMask is that it can allow input of variable length. The disadvantage is that it can be applied only in very specific use-cases. The problem is that the Regex needs to match all incomplete versions of the input value which can be very challenging for non-trivial use-cases.

The following example restricts user input to digits only on the left and restricts input to Russian postal codes (first digit between 1 and 6, total of 6 digits) on the right.

^\d+$
^[1-6]\d{0,5}$
Number:
Russian ZIP:
<MudGrid Class="justify-space-between" Style="max-width: 800px;">
    <MudItem  xs="12" sm="6">
        <MudTextField Mask="@mask1" Label="Only digits (unlimited length)"  HelperText="@mask1.Mask"
                      @bind-Value="numbers"  Variant="@Variant.Text" Clearable />
    </MudItem>
    <MudItem  xs="12" sm="6">
        <MudTextField Mask="@mask2" Label="Russian postal code" HelperText="@mask2.Mask"
                      @bind-Value="russianZip"  Variant="@Variant.Text" Clearable />
    </MudItem>
    <MudItem  xs="12" sm="6">
        Number: <b>@numbers</b>
    </MudItem>
    <MudItem  xs="12" sm="6">
        Russian ZIP: <b>@russianZip</b>
    </MudItem>
</MudGrid>
@code {
    public string numbers, russianZip;

    public IMask mask1 = new RegexMask(@"^\d+$");

    public IMask mask2 = new RegexMask(@"^[1-6]\d{0,5}$");

}
RegexMask.IPv4

RegexMask.IPv4() is a predefined RegexMask for an IPv4 Address with or without port masking.

000.000.000.000
000.000.000.000:00000
IPv4:
IPv4 w/Port:
<MudGrid Class="justify-space-between" Style="max-width: 800px;">
    <MudItem xs="12" sm="6">
        <MudTextField Mask="@ipv4Mask" Label="IPv4 Address"  HelperText="@ipv4Mask.Mask"
                      @bind-Value="ip"  Variant="@Variant.Text" Clearable />
    </MudItem>
    <MudItem xs="12" sm="6">
        <MudTextField Mask="@ipv4PortMask" Label="IPv4 Address with Port"  HelperText="@ipv4PortMask.Mask"
                      @bind-Value="ipPort"  Variant="@Variant.Text" Clearable />
    </MudItem>
    <MudItem xs="12" sm="6">
        IPv4: <b>@ip</b>
    </MudItem>
    <MudItem xs="12" sm="6">
        IPv4 w/Port: <b>@ipPort</b>
    </MudItem>
</MudGrid>
@code {
    public string ip;
    public string ipPort;
    public IMask ipv4Mask = RegexMask.IPv4();
    public IMask ipv4PortMask = RegexMask.IPv4(true);
}
RegexMask.IPv6

RegexMask.IPv6() is a predefined RegexMask for an IPv6 Address with or without port masking.

XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX
[XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX]:00000
IPv4:
IPv4 w/Port:
<MudGrid Class="justify-space-between" Style="max-width: 800px;">
    <MudItem xs="12" sm="6">
        <MudTextField Mask="@ipv6Mask" Label="IPv6 Address"  HelperText="@ipv6Mask.Mask"
                      @bind-Value="ip"  Variant="@Variant.Text" Clearable />
    </MudItem>
    <MudItem xs="12" sm="6">
        <MudTextField Mask="@ipv6PortMask" Label="IPv6 Address with Port"  HelperText="@ipv6PortMask.Mask"
                      @bind-Value="ipPort"  Variant="@Variant.Text" Clearable />
    </MudItem>
    <MudItem xs="12" sm="6">
        IPv4: <b>@ip</b>
    </MudItem>
    <MudItem xs="12" sm="6">
        IPv4 w/Port: <b>@ipPort</b>
    </MudItem>
</MudGrid>
@code {
    public string ip;
    public string ipPort;
    public IMask ipv6Mask = RegexMask.IPv6();
    public IMask ipv6PortMask = RegexMask.IPv6(true);
}
RegexMask.Email

RegexMask.Email() is a predefined RegexMask for an Email Address.

Ex. user@domain.com
<user>@<domain.com>
Email 1:
Email 2:
<MudGrid Class="justify-space-between" Style="max-width: 800px;">
    <MudItem xs="12" sm="6">
        <MudTextField Mask="@emailMask" Label="Email Address"  HelperText="@emailMask.Mask"
                      @bind-Value="email"  Variant="@Variant.Text" Clearable />
    </MudItem>
    <MudItem xs="12" sm="6">
        <MudTextField Mask="@emailCustomMask" Label="Email Address with Custom Mask"  HelperText="@emailCustomMask.Mask"
                      @bind-Value="email2"  Variant="@Variant.Text" Clearable />
    </MudItem>
    <MudItem xs="12" sm="6">
        Email 1: <b>@email</b>
    </MudItem>
    <MudItem xs="12" sm="6">
        Email 2: <b>@email2</b>
    </MudItem>
</MudGrid>
@code {
    public string email;
    public string email2;
    public IMask emailMask = RegexMask.Email();
    public IMask emailCustomMask = RegexMask.Email("<user>@<domain.com>");
}
BlockMask

BlockMask can match blocks of uniform patterns with a variable length (min, max) with delimiters in between. In this example we show a BlockMask that matches all of the following flight numbers LH4234, RUS1727, OS1 and H028.

Flight number:
<MudGrid Class="justify-space-between" Style="max-width: 400px;">
    <MudItem xs="12">
        <MudTextField Mask="@mask" Label="Flight number" 
                      @bind-Value="text"  Variant="@Variant.Outlined" Clearable />
    </MudItem>
    <MudItem xs="12">
        Flight number: <b>@text</b>
    </MudItem>
</MudGrid>
@code {
    public string text { get; set; }

    IMask mask = new BlockMask(delimiters:" ", new Block('a', 1,3), new Block('0', 1,4));
}
Implement your own Mask

To write your own custom mask either derive your own from one of our masking algorithms or implement the interface IMask.

An unhandled error has occurred. Reload 🗙