MudBlazor

Community Support

Discord

GitHub Discussions

Tools and resources

TryMudBlazor

Templates

Sponsor

Open Collective


Switch to Blazor wasm
Toggle light/dark theme
GitHub repository
Toggle right-to-left/left-to-right

Community Support

Discord

GitHub Discussions

Tools and resources

TryMudBlazor

Templates

Sponsor

Open Collective

Autocomplete

The Autocomplete component offers simple and flexible type-ahead functionality. It is great for searching a value from a long list of options. In comparison to a Select, the Autocomplete doesn't need to know the complete item list, it only calls a search function which will return matching items. The search function can even run asynchronously, i.e. for database queries.

See Autocomplete API for parameter documentation.

Usage

How you write the search function determines whether or not the Autocomplete shows a full list initially. By setting ResetValueOnEmptyText="true", the Value will be reset when the user clears the input text. With CoerceText="true" upon selection of an entry from the list, the Text is always updated. When the user types something that is not on the list and CoerceValue is true, the Value will be overwritten with the user input which allows it to be passed to the validation function.

Not selected
Not selected

Show code example
Edit on TryMudBlazor
Copy Code
View the source on GitHub
<MudGrid>
    <MudItem xs="12" sm="6" md="4">
        <MudAutocomplete T="string" Label="US States" @bind-Value="value1" SearchFunc="@Search1" 
                         ResetValueOnEmptyText="@resetValueOnEmptyText" 
                         CoerceText="@coerceText" CoerceValue="@coerceValue"/>
    </MudItem>
    <MudItem xs="12" sm="6" md="4">
        <MudAutocomplete T="string" Label="US States" @bind-Value="value2" SearchFunc="@Search2" 
                         ResetValueOnEmptyText="@resetValueOnEmptyText" 
                         CoerceText="@coerceText"  CoerceValue="@coerceValue"
                         AdornmentIcon="@Icons.Material.Filled.Search" AdornmentColor="Color.Primary" />
    </MudItem>
    <MudItem xs="12" md="12">
        <MudText Class="mb-n3" Typo="Typo.body2">
            <MudChip>@(value1 ?? "Not selected")</MudChip><MudChip>@(value2 ?? "Not selected")</MudChip>
        </MudText>
    </MudItem>
    <MudItem xs="12" md="12" class="flex-column">
        <MudSwitch @bind-Checked="resetValueOnEmptyText" Color="Color.Primary">Reset Value on empty Text</MudSwitch>
        <MudSwitch @bind-Checked="coerceText" Color="Color.Secondary">Coerce Text to Value</MudSwitch>
        <MudSwitch @bind-Checked="coerceValue" Color="Color.Tertiary">Coerce Value to Text (if not found)</MudSwitch>
    </MudItem>
</MudGrid>
@code {
    private bool resetValueOnEmptyText;
    private bool coerceText;
    private bool coerceValue;
    private string value1, value2;
    private string[] states =
    {
        "Alabama", "Alaska", "American Samoa", "Arizona",
        "Arkansas", "California", "Colorado", "Connecticut",
        "Delaware", "District of Columbia", "Federated States of Micronesia",
        "Florida", "Georgia", "Guam", "Hawaii", "Idaho",
        "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky",
        "Louisiana", "Maine", "Marshall Islands", "Maryland",
        "Massachusetts", "Michigan", "Minnesota", "Mississippi",
        "Missouri", "Montana", "Nebraska", "Nevada",
        "New Hampshire", "New Jersey", "New Mexico", "New York",
        "North Carolina", "North Dakota", "Northern Mariana Islands", "Ohio",
        "Oklahoma", "Oregon", "Palau", "Pennsylvania", "Puerto Rico",
        "Rhode Island", "South Carolina", "South Dakota", "Tennessee",
        "Texas", "Utah", "Vermont", "Virgin Island", "Virginia",
        "Washington", "West Virginia", "Wisconsin", "Wyoming",
    };

    private async Task<IEnumerable<string>> Search1(string value)
    {
        // In real life use an asynchronous function for fetching data from an api.
        await Task.Delay(5);

        // if text is null or empty, show complete list
        if (string.IsNullOrEmpty(value))
            return states;
        return states.Where(x => x.Contains(value, StringComparison.InvariantCultureIgnoreCase));
    }

    private async Task<IEnumerable<string>> Search2(string value)
    {
        // In real life use an asynchronous function for fetching data from an api.
        await Task.Delay(5);

        // if text is null or empty, don't return values (drop-down will not open)
        if (string.IsNullOrEmpty(value))
            return new string[0];
        return states.Where(x => x.Contains(value, StringComparison.InvariantCultureIgnoreCase));
    }
}

Presentation

When you use objects, Autocomplete uses ToString() to convert the object into text form. You can set a custom ToStringFunc to override how the list items are stringified. This string representation is also what you'll get as input to the search function.
If that is not enough, you can define an <ItemTemplate> and even an <ItemSelectedTemplate> to create highly sophisticated list item presentations.

Selected values:

Not selected
Not selected

Show code example
Edit on TryMudBlazor
Copy Code
View the source on GitHub
@using System.Net.Http.Json
@using MudBlazor.Examples.Data.Models
@inject HttpClient httpClient

<MudGrid>
    <MudItem xs="12" sm="6" md="4">
        <MudAutocomplete T="Element" Label="Periodic Table Element" @bind-Value="value1" 
                         SearchFunc="@Search" ToStringFunc="@(e=> e==null?null : $"{e.Name} ({e.Sign})")" />
    </MudItem>
    <MudItem xs="12" sm="6" md="4">
        <MudAutocomplete T="Element" Label="Periodic Table Element" @bind-Value="value2" 
                         SearchFunc="@Search" ToStringFunc="@(e=> e==null?null : $"{e.Name} ({e.Sign})")">
            <ItemTemplate Context="e">                          
                <MudText>
                    <MudIcon Icon="@Icons.Material.Filled.CheckBoxOutlineBlank" Class="mb-n1 mr-3"/>@($"{e.Name} ({e.Sign})")
                </MudText>
            </ItemTemplate>
            <ItemSelectedTemplate Context="e">                
                <MudText>
                    <MudIcon Icon="@Icons.Material.Filled.CheckBox" Class="mb-n1 mr-3"/>@($"{e.Name} ({e.Sign})")
                </MudText>
            </ItemSelectedTemplate>
        </MudAutocomplete>
    </MudItem>
    <MudItem xs="12" md="12">
        <MudText Class="mb-n3" Typo="Typo.body2">
            Selected values: <MudChip>@(value1?.ToString() ?? "Not selected")</MudChip><MudChip>@(value2?.ToString() ?? "Not selected")</MudChip>
        </MudText>
    </MudItem>
</MudGrid>
@code {
    private Element value1, value2;

    private async Task<IEnumerable<Element>> Search(string value)
    {
        return  await httpClient.GetFromJsonAsync<List<Element>>($"webapi/periodictable/{value}");
    }
}

Validation

Below there are different examples of validation with the MudAutocomplete control. The validation uses an EditForm or a MudForm. The result and display will vary if the <CoerceValue> option is set to <true>. But also if characters are typed into the control instead of a selection from the dropdown list.
For more info on form validation, check out Form.

IsTouched: False, IsValid: False

Not selected
Not selected
Not selected

Show code example
Edit on TryMudBlazor
Copy Code
View the source on GitHub
@using System.ComponentModel.DataAnnotations

<MudGrid>
    <MudItem xs="12" sm="6" md="4">
        <EditForm EditContext="editContext1">
        <DataAnnotationsValidator />
            <MudAutocomplete Label="US States" @bind-Value="choice1.State" Required="true"
             SearchFunc="@SearchAsync" Immediate="true" CoerceValue="@coerceValue" ResetValueOnEmptyText="true"
             AdornmentIcon="@Icons.Material.Filled.Search" AdornmentColor="Color.Primary"
             For="@(() => choice1.State)"/>
            <MudButton ButtonType="ButtonType.Button" Variant="Variant.Filled" Color="Color.Primary" 
             Class="ml-auto mt-3 mb-3" OnClick="@(()=>success1=editContext1.Validate())">Validate</MudButton>
                   @if (success1)
                   {
                       <MudText Color="Color.Success">Success</MudText>
                   }
        </EditForm>
    </MudItem>
    <MudItem xs="12" sm="6" md="4">
        <EditForm EditContext="editContext2">
        <DataAnnotationsValidator />
            <MudAutocomplete Label="US States" @bind-Value="choice2.State" Required="true"
             SearchFunc="@SearchAsync" Immediate="true" CoerceValue="@coerceValue" ResetValueOnEmptyText="true"
             OpenIcon="@Icons.Material.Filled.Search" AdornmentColor="Color.Secondary"
             Validation="@(new Func<string, IEnumerable<string>>(Validate))" />
            <MudButton ButtonType="ButtonType.Button" Variant="Variant.Filled" Color="Color.Primary" 
                       Class="ml-auto mt-3 mb-3" OnClick="@(()=>success2=editContext2.Validate())">Validate</MudButton>
                   @if (success2)
                   {
                       <MudText Color="Color.Success">Success</MudText>
                   }
        </EditForm>
    </MudItem>
    <MudItem xs="12" sm="6" md="4">
        <MudForm @ref="form">
            <MudAutocomplete T="string" Label="US States" @bind-Value="choice3.State" Required="true"
             SearchFunc="@SearchAsync" Immediate="true" CoerceValue="@coerceValue" ResetValueOnEmptyText="true"
             CloseIcon="@Icons.Material.Filled.Search" AdornmentColor="Color.Tertiary"
             Validation="@(new Func<string, IEnumerable<string>>(Validate))" />
            <MudButton Variant="Variant.Filled" Color="Color.Primary" Class="ml-auto mt-3 mb-3" 
             OnClick="@(()=>form.Validate())">Validate</MudButton>
                    @if (form.IsTouched && form.IsValid)
                    {
                        <MudText Color="Color.Success">Success</MudText>
                    }
                    else
                    {
                        <MudText>IsTouched: @form.IsTouched, IsValid: @form.IsValid</MudText>
                    }
        </MudForm>
	</MudItem>
    <MudItem xs="12" md="12">
        <MudText Class="mb-n3" Typo="Typo.body2">
            <MudChip>@(choice1.State ?? "Not selected")</MudChip><MudChip>@(choice2.State ?? "Not selected")</MudChip><MudChip>@(choice3.State ?? "Not selected")</MudChip>
        </MudText>
    </MudItem>
    <MudItem xs="12" md="12" class="flex-column">
        <MudSwitch @bind-Checked="coerceValue" Color="Color.Tertiary">Coerce Value to Text (if not found)</MudSwitch>
    </MudItem>
</MudGrid>
@code {
    private MudForm form;
    private bool coerceValue;
    private bool success1;
    private bool success2;
    private Choice choice1 = new();
    private Choice choice2 = new();
    private Choice choice3 = new();
    private EditContext editContext1;
    private EditContext editContext2;

    protected override void OnInitialized()
    {
        editContext1 = new EditContext(choice1);
        editContext2 = new EditContext(choice2);
    } 

    private static string[] states =
    {
        "Alabama", "Alaska", "American Samoa", "Arizona",
        "Arkansas", "California", "Colorado", "Connecticut",
        "Delaware", "District of Columbia", "Federated States of Micronesia",
        "Florida", "Georgia", "Guam", "Hawaii", "Idaho",
        "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky",
        "Louisiana", "Maine", "Marshall Islands", "Maryland",
        "Massachusetts", "Michigan", "Minnesota", "Mississippi",
        "Missouri", "Montana", "Nebraska", "Nevada",
        "New Hampshire", "New Jersey", "New Mexico", "New York",
        "North Carolina", "North Dakota", "Northern Mariana Islands", "Ohio",
        "Oklahoma", "Oregon", "Palau", "Pennsylvania", "Puerto Rico",
        "Rhode Island", "South Carolina", "South Dakota", "Tennessee",
        "Texas", "Utah", "Vermont", "Virgin Island", "Virginia",
        "Washington", "West Virginia", "Wisconsin", "Wyoming",
    };

    private async Task<IEnumerable<string>> SearchAsync(string value)
    {
        // In real life use an asynchronous function for fetching data from an api.
        await Task.Delay(5);

        // if text is null or empty, show complete list
        if (string.IsNullOrEmpty(value))
        {
            return states;
        }

        return states.Where(x => x.Contains(value, StringComparison.InvariantCultureIgnoreCase));
    }

    private IEnumerable<string> Validate(string value)
    {        
        if (string.IsNullOrWhiteSpace(value))
        {
            yield return "The State field is required";
            yield break;
        }

        if (!states.Contains(value))
        {
            yield return "This is an incorrect value";
        }
    }

    public class Choice
    {
        [Required]
        [State]
        public string State { get; set;}
    }

    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter)]
    public sealed class StateAttribute : ValidationAttribute
    {
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (!states.Contains(value))
            {
                return new ValidationResult("This is an incorrect value", new[] { validationContext.MemberName });
            }

            return null;
        }
    }
}
An error has occurred. This application may no longer respond until reloaded. Reload 🗙