Blazorise Autocomplete component

The Autocomplete component offers simple and flexible type-ahead functionality.

See Autocomplete specifications for behavior details and edge cases.

The Autocomplete component provides suggestions while you type into the field. The component is in essence a text box which, at runtime, filters data in a drop-down by a Filter operator when a user captures a value. You may also enable FreeTyping and Autocomplete can be used to just provide suggestions based on user input.

To use the Autocomplete component, install the Blazorise.Components package first.

Installation

NuGet

Install extension from NuGet.
dotnet add package Blazorise.Components

Imports

In your main _Imports.razor add:
@using Blazorise.Components

Examples

Single selection

Selected search value:
Selected text value:
<Autocomplete TItem="Country"
              TValue="string"
              Data="@Countries"
              TextField="@(( item ) => item.Name)"
              ValueField="@(( item ) => item.Iso)"
              @bind-SelectedValue="@selectedSearchValue"
              @bind-SelectedText="selectedAutoCompleteText"
              Placeholder="Search..."
              Filter="AutocompleteFilter.StartsWith"
              FreeTyping
              CustomFilter="@(( item, searchValue ) => item.Name.IndexOf( searchValue, 0, StringComparison.CurrentCultureIgnoreCase ) >= 0 )">
    <NotFoundTemplate> Sorry... @context was not found! :( </NotFoundTemplate>
</Autocomplete>

<Field Horizontal>
    <FieldBody ColumnSize="ColumnSize.Is12">
        Selected search value: @selectedSearchValue
    </FieldBody>
    <FieldBody ColumnSize="ColumnSize.Is12">
        Selected text value: @selectedAutoCompleteText
    </FieldBody>
</Field>
@code {
    private readonly CountryData CountryData = new();
    public IEnumerable<Country> Countries;

    protected override async Task OnInitializedAsync()
    {
        Countries = await CountryData.GetDataAsync();
        await base.OnInitializedAsync();
    }

    public string selectedSearchValue { get; set; }
    public string selectedAutoCompleteText { get; set; }
}

Multiple selection

Selected Values: AE,AL
Selected Texts: United Arab Emirates,Albania
<Autocomplete TItem="Country"
              TValue="string"
              Data="@Countries"
              TextField="@(( item ) => item.Name)"
              ValueField="@(( item ) => item.Iso)"
              Placeholder="Search..."
              SelectionMode="AutocompleteSelectionMode.Multiple"
              FreeTyping
              @bind-SelectedValues="multipleSelectionData"
              @bind-SelectedTexts="multipleSelectionTexts">
</Autocomplete>

<Field Horizontal>
    <FieldBody ColumnSize="ColumnSize.Is12">
        Selected Values: @string.Join(',', multipleSelectionData)
    </FieldBody>
    <FieldBody ColumnSize="ColumnSize.Is12">
        Selected Texts: @(multipleSelectionTexts == null ? null : string.Join(',', multipleSelectionTexts))
    </FieldBody>
</Field>
@code {
    [Inject]
    public CountryData CountryData { get; set; }
    public IEnumerable<Country> Countries;

    protected override async Task OnInitializedAsync()
    {
        Countries = await CountryData.GetDataAsync();
        multipleSelectionData = new List<string>() { Countries.ElementAt( 1 ).Iso, Countries.ElementAt( 3 ).Iso };
        await base.OnInitializedAsync();
    }

    List<string> multipleSelectionData;
    List<string> multipleSelectionTexts;
}

Validation (single)

Wrap the Autocomplete in a Validation container to integrate with the standard validation system.
<Validations @ref="validations" Mode="ValidationMode.Manual">
    <Validation Validator="@ValidationRule.IsNotEmpty">
        <Field>
            <FieldLabel>Country</FieldLabel>
            <FieldBody>
                <Autocomplete TItem="Country"
                              TValue="string"
                              Data="@Countries"
                              TextField="@(( item ) => item.Name)"
                              ValueField="@(( item ) => item.Iso)"
                              Placeholder="Select a country"
                              @bind-SelectedValue="@selectedCountry">
                    <Feedback>
                        <ValidationError>Please select a country.</ValidationError>
                    </Feedback>
                </Autocomplete>
            </FieldBody>
        </Field>
    </Validation>
    <Button Color="Color.Primary" Clicked="@Validate">Validate</Button>
</Validations>
@code {
    private readonly CountryData CountryData = new();

    public IEnumerable<Country> Countries;

    Validations validations;

    string selectedCountry;

    protected override async Task OnInitializedAsync()
    {
        Countries = await CountryData.GetDataAsync();
        await base.OnInitializedAsync();
    }

    async Task Validate()
    {
        await validations.ValidateAll();
    }
}

Validation (multiple)

When using AutocompleteSelectionMode.Multiple, validate the SelectedValues list to enforce at least one selection.
<Validations @ref="validations" Mode="ValidationMode.Manual">
    <Validation Validator="@ValidateSelection">
        <Field>
            <FieldLabel>Countries</FieldLabel>
            <FieldBody>
                <Autocomplete TItem="Country"
                              TValue="string"
                              Data="@Countries"
                              TextField="@(( item ) => item.Name)"
                              ValueField="@(( item ) => item.Iso)"
                              SelectionMode="AutocompleteSelectionMode.Multiple"
                              Placeholder="Select countries"
                              @bind-SelectedValues="@selectedCountries">
                    <Feedback>
                        <ValidationError>Please select at least one country.</ValidationError>
                    </Feedback>
                </Autocomplete>
            </FieldBody>
        </Field>
    </Validation>
    <Button Color="Color.Primary" Clicked="@Validate">Validate</Button>
</Validations>
@code {
    private readonly CountryData CountryData = new();

    public IEnumerable<Country> Countries;

    Validations validations;

    List<string> selectedCountries = new List<string>();

    protected override async Task OnInitializedAsync()
    {
        Countries = await CountryData.GetDataAsync();
        await base.OnInitializedAsync();
    }

    void ValidateSelection( ValidatorEventArgs validationArgs )
    {
        List<string> values = validationArgs.Value as List<string>;

        validationArgs.Status = values != null && values.Count > 0
            ? ValidationStatus.Success
            : ValidationStatus.Error;
    }

    async Task Validate()
    {
        await validations.ValidateAll();
    }
}

Validation

Use ValidationMode.Auto with a model decorated with data annotations to validate single and multiple selections.

@using System.ComponentModel.DataAnnotations

<Validations Mode="ValidationMode.Auto" Model="@model">
    <Validation>
        <Field>
            <FieldLabel>Country</FieldLabel>
            <FieldBody>
                <Autocomplete TItem="Country"
                              TValue="string"
                              Data="@Countries"
                              TextField="@(( item ) => item.Name)"
                              ValueField="@(( item ) => item.Iso)"
                              Placeholder="Select a country"
                              @bind-SelectedValue="@model.CountryIso">
                    <Feedback>
                        <ValidationError />
                    </Feedback>
                </Autocomplete>
            </FieldBody>
        </Field>
    </Validation>
    <Validation>
        <Field>
            <FieldLabel>Countries</FieldLabel>
            <FieldBody>
                <Autocomplete TItem="Country"
                              TValue="string"
                              Data="@Countries"
                              TextField="@(( item ) => item.Name)"
                              ValueField="@(( item ) => item.Iso)"
                              SelectionMode="AutocompleteSelectionMode.Multiple"
                              Placeholder="Select countries"
                              @bind-SelectedValues="@model.CountryIsos">
                    <Feedback>
                        <ValidationError />
                    </Feedback>
                </Autocomplete>
            </FieldBody>
        </Field>
    </Validation>
</Validations>
@code {
    private readonly CountryData CountryData = new();

    public IEnumerable<Country> Countries;

    AutocompleteValidationModel model = new AutocompleteValidationModel();

    protected override async Task OnInitializedAsync()
    {
        Countries = await CountryData.GetDataAsync();
        await base.OnInitializedAsync();
    }

    public class AutocompleteValidationModel
    {
        [Required( ErrorMessage = "Please select a country." )]
        public string CountryIso { get; set; }

        [MinLength( 1, ErrorMessage = "Please select at least one country." )]
        public List<string> CountryIsos { get; set; } = new List<string>();
    }
}

ReadData

Frequently, you'll want to read data on demand rather than loading everything into memory at startup. You can do it with the ReadData API. It will provide you with enough information for you to call an external data-source, which will return new data, which you can then reassign to the Data parameter.
Selected search value:
Selected text value:
<Autocomplete TItem="Country"
              TValue="string"
              Data="@ReadDataCountries"
              ReadData="@OnHandleReadData"
              TextField="@(( item ) => item.Name)"
              ValueField="@(( item ) => item.Iso)"
              @bind-SelectedValue="@selectedSearchValue"
              @bind-SelectedText="selectedAutoCompleteText"
              Placeholder="Search..."
              FreeTyping>
    <NotFoundTemplate> Sorry... @context was not found! :( </NotFoundTemplate>
</Autocomplete>

<Field Horizontal>
    <FieldBody ColumnSize="ColumnSize.Is12">
        Selected search value: @selectedSearchValue
    </FieldBody>
    <FieldBody ColumnSize="ColumnSize.Is12">
        Selected text value: @selectedAutoCompleteText
    </FieldBody>
</Field>
@code {
    private readonly CountryData CountryData = new();
    public IEnumerable<Country> Countries;
    public IEnumerable<Country> ReadDataCountries;

    private Random random = new();

    public string selectedSearchValue { get; set; }
    public string selectedAutoCompleteText { get; set; }

    protected override async Task OnInitializedAsync()
    {
        Countries = await CountryData.GetDataAsync();
        await base.OnInitializedAsync();
    }

    private async Task OnHandleReadData( AutocompleteReadDataEventArgs autocompleteReadDataEventArgs )
    {
        if ( !autocompleteReadDataEventArgs.CancellationToken.IsCancellationRequested )
        {
            await Task.Delay( random.Next( 100 ) );
            if ( !autocompleteReadDataEventArgs.CancellationToken.IsCancellationRequested )
            {
                ReadDataCountries = Countries.Where( x => x.Name.StartsWith( autocompleteReadDataEventArgs.SearchValue, StringComparison.InvariantCultureIgnoreCase ) );
            }
        }
    }
}

Custom content

Customize the way you display the Autocomplete items by providing ItemContent.
Selected search value:
Selected text value:
<Autocomplete TItem="Country"
              TValue="string"
              Data="@Countries"
              TextField="@(( item ) => item.Name)"
              ValueField="@(( item ) => item.Iso)"
              @bind-SelectedValue="@selectedSearchValue"
              @bind-SelectedText="selectedAutoCompleteText"
              Placeholder="Search..."
              Filter="AutocompleteFilter.StartsWith"
              FreeTyping
              CustomFilter="@(( item, searchValue ) => item.Name.IndexOf( searchValue, 0, StringComparison.CurrentCultureIgnoreCase ) >= 0 )">
    <NotFoundTemplate> Sorry... @context was not found! :( </NotFoundTemplate>
    <ItemContent>
        <Div Flex="Flex.InlineFlex.JustifyContent.Between" Width="Width.Is100">
            <Heading Margin="Margin.Is2.FromBottom">@context.Value</Heading>
            <Small>@context.Item.Capital</Small>
        </Div>
        <Paragraph Margin="Margin.Is2.FromBottom">@context.Text</Paragraph>
    </ItemContent>
</Autocomplete>

<Field Horizontal>
    <FieldBody ColumnSize="ColumnSize.Is12">
        Selected search value: @selectedSearchValue
    </FieldBody>
    <FieldBody ColumnSize="ColumnSize.Is12">
        Selected text value: @selectedAutoCompleteText
    </FieldBody>
</Field>
@code {
    private readonly CountryData CountryData = new();
    public IEnumerable<Country> Countries;

    protected override async Task OnInitializedAsync()
    {
        Countries = await CountryData.GetDataAsync();
        await base.OnInitializedAsync();
    }
    string selectedSearchValue { get; set; }
    string selectedAutoCompleteText { get; set; }
}

Selected items

Enabling `AutocompleteSelectionMode.Checkbox` adds checkboxes to all items in the autocomplete menu, while also keeping previously selected items visible. Note: Make sure to set CloseOnSelection to false if you want to keep the dropdown open whenever an item is selected.
Selected Values: AE,AL
Selected Texts: United Arab Emirates,Albania
<Autocomplete TItem="Country"
              TValue="string"
              Data="@Countries"
              TextField="@(( item ) => item.Name)"
              ValueField="@(( item ) => item.Iso)"
              Placeholder="Search..."
              SelectionMode="AutocompleteSelectionMode.Checkbox"
              CloseOnSelection="false"
              @bind-SelectedValues="multipleSelectionData"
              @bind-SelectedTexts="multipleSelectionTexts">
</Autocomplete>

<Field Horizontal>
    <FieldBody ColumnSize="ColumnSize.Is12">
        Selected Values: @string.Join(',', multipleSelectionData)
    </FieldBody>
    <FieldBody ColumnSize="ColumnSize.Is12">
        Selected Texts: @(multipleSelectionTexts == null ? null : string.Join(',', multipleSelectionTexts))
    </FieldBody>
</Field>
@code {
    [Inject]
    public CountryData CountryData { get; set; }
    public IEnumerable<Country> Countries;

    protected override async Task OnInitializedAsync()
    {
        Countries = await CountryData.GetDataAsync();
        multipleSelectionData = new List<string>() { Countries.ElementAt( 1 ).Iso, Countries.ElementAt( 3 ).Iso };
        await base.OnInitializedAsync();
    }

    List<string> multipleSelectionData;
    List<string> multipleSelectionTexts;
}

Text highlighting

Autocomplete HighlightSearch is a feature that allows you to highlight the search text that you have entered in a dropdown list of items. When you start typing in the search field, the dropdown list of items will automatically be filtered to show only the items that match the search text. The search text will also be highlighted in the dropdown list of items, so that you can easily see which items match your search. This can be a useful feature when you are trying to find a specific item in a long list of items, as it allows you to quickly locate the item you are looking for.
<Autocomplete TItem="Country"
              TValue="string"
              Data="@Countries"
              TextField="@(( item ) => item.Name)"
              ValueField="@(( item ) => item.Iso)"
              Placeholder="Search..."
              HighlightSearch>
    <NotFoundTemplate> Sorry... @context was not found! :( </NotFoundTemplate>
</Autocomplete>
@code {
    private readonly CountryData CountryData = new();
    public IEnumerable<Country> Countries;

    protected override async Task OnInitializedAsync()
    {
        Countries = await CountryData.GetDataAsync();
        await base.OnInitializedAsync();
    }
}

Virtualize

Blazorise Autocomplete's Virtualize feature allows for loading data on demand while scrolling, which improves the performance of the component when working with large datasets. With Virtualize, the Autocomplete component only loads the items that are currently visible in the list, and as the user scrolls, more items are loaded in the background. This allows for a much faster and smoother user experience, especially when working with large lists of items.

This feature can be easily enabled by setting the Virtualize property to "true" on the Autocomplete component.

<Autocomplete TItem="Country"
              TValue="string"
              Data="@Countries"
              TextField="@(( item ) => item.Name)"
              ValueField="@((item) => item.Iso)"
              @bind-SelectedValue="selectedSearchValue"
              Placeholder="Search..."
              Virtualize>
    <NotFoundTemplate> Sorry... @context was not found! :( </NotFoundTemplate>
</Autocomplete>
@code {
    private readonly CountryData CountryData = new();
    public IEnumerable<Country> Countries;

    protected override async Task OnInitializedAsync()
    {
        Countries = await CountryData.GetDataAsync();
        await base.OnInitializedAsync();
    }

    public string selectedSearchValue { get; set; }
}

Virtualization

Blazorise Autocomplete's Virtualize and ReadData features work together to handle large datasets efficiently. The ReadData event allows you to load only the data needed for the current interaction, without loading the entire dataset into memory. Meanwhile, the Virtualize property ensures that only the visible items are rendered in the DOM, significantly improving performance when working with large lists.

In the provided example, the dataset is represented using IEnumerable for simplicity, but in real-world scenarios, you would typically use IQueryable. This allows for true deferred execution, ensuring only the required data is fetched and processed.

To enable Virtualize with ReadData, you must also set the TotalItems property. The TotalItems value represents the total count of items in your dataset and is required for proper virtualization.

<Autocomplete TItem="Country"
              TValue="string"
              Data="@ReadDataCountries"
              TotalItems="totalCountries"
              TextField="@(( item ) => item.Name)"
              ValueField="@((item) => item.Iso)"
              @bind-SelectedValue="@SelectedSearchValue"
              Placeholder="Search..."
              Virtualize
              ReadData="@OnHandleReadData">
    <NotFoundTemplate> Sorry... @context was not found! :( </NotFoundTemplate>
</Autocomplete>
@code {
    private readonly CountryData CountryData = new();

    public IEnumerable<Country> Countries;
    IEnumerable<Country> ReadDataCountries;
    int totalCountries;

    public string SelectedSearchValue { get; set; }

    protected override async Task OnInitializedAsync()
    {
        Countries = await CountryData.GetDataAsync();
        totalCountries = Countries.Count();
        await base.OnInitializedAsync();
    }

    private Task OnHandleReadData( AutocompleteReadDataEventArgs autocompleteReadDataEventArgs )
    {
        if ( !autocompleteReadDataEventArgs.CancellationToken.IsCancellationRequested )
        {
            ReadDataCountries = Countries
                .Where(x => x.Name.StartsWith(autocompleteReadDataEventArgs.SearchValue, StringComparison.InvariantCultureIgnoreCase))
                .Skip(autocompleteReadDataEventArgs.VirtualizeOffset).Take(autocompleteReadDataEventArgs.VirtualizeCount);
        }

        return Task.CompletedTask;
    }
}

API

See the API reference for the parameters, events, methods, and related types available to the components covered on this page.

On this page