New to Telerik UI for Blazor? Download free 30-day trial

AutoComplete Virtualization

The AutoComplete component can virtualize the elements in its dropdown so you can use huge data source without UI performance issues.

Enabling the UI virtualization feature makes the component reuse a set number of items in the dropdown as you scroll, instead of rendering out the entire data source. It can work both with local data that the view-model already has, or you can fetch remote data every time the user scrolls through an event the component provides.

In This Article

Display, scroll and filter over 10k records in the AutoComplete without delays and performance issues.

Virtual Scrolling of large local data


This section will explain the parameters and behaviors that are related to the virtualization feature so you can set it up.

To enable UI virtualization, you need to set the following parameters of the component:

  • ScrollMode - Telerik.Blazor.DropDownScrollMode - set it to DropDownScrollMode.Virtual. It defaults to the "regular" scrolling.
  • Height - string - set the height in the nested popup settings tag of the component. It must not be a null/empty string.
  • ItemHeight - decimal - set it to the height each individual item will have in the dropdown. Make sure to accommodate the content your items will have and any item template.
  • PageSize - int - defines how many items will actually be rendered and reused. The value determines how many items are loaded on each scroll. The number of items must be large enough according to the ItemHeight and popup Height, so that there are more items than the dropdown so there is a scrollbar.

You can find a basic example in the Local Data section below.

For working with remote data, you also need:

  • OnRead - EventCallback - the component will call this event when the user scrolls with the corresponding offset (Skip), PageSize and any filters. This lets you optimize the data queries and return only what is needed at the moment, when it is needed. Set the args.Data and args.Total properties of the event argument object.


  • When the initially selected item/items are on a page different than the first one, opening the dropdown list will NOT scroll the list to the selected item.
  • When virtualization is enabled, the component calculates the position of the items. In this case, the loading indicators are not displayed as they would affect the proper item positioning. This limitation will be removed in a future version of UI for Blazor.

Local Data Example

<br />
<TelerikAutoComplete Data="@Data"

                     Filterable="true" FilterOperator="@StringFilterOperator.Contains">
        <AutoCompletePopupSettings Height="200px" />

@code {
    string SelectedValue { get; set; }
    List<string> Data { get; set; }

    protected override void OnInitialized()
        Data = Enumerable.Range(1, 12345).Select(x => $"Name {x}").ToList();


    public class Person
        public int Id { get; set; }
        public string Name { get; set; }

Remote Data Example

This example showcases sample implementations of:

  • An async remote service that returns the data. It is mocked by a static class for this example, you can refactor as needed, and you can find examples of serializing it over the wire in this collection of sample projects for the grid component - the approach is identical.
  • An OnRead event handler that calls that service.

Run this and see how you can display, scroll and filter over 10k records in the AutoComplete without delays and performance issues from a remote endpoint. There is artificial delay in these operations for the sake of the demonstration.

@using Telerik.DataSource
@using Telerik.DataSource.Extensions


<TelerikAutoComplete TItem="@String"
        <AutoCompletePopupSettings Height="300px" />

@code {
    string AutoCompleteValue { get; set; } = "Name 1234"; // pre-select an item to showcase it works like in a regular textbox

    async Task GetRemoteData(AutoCompleteReadEventArgs args)
        DataEnvelope<string> result = await MyService.GetItems(args.Request);

        args.Data = result.Data;
        args.Total = result.Total;

    // mimics a real service in terms of API appearance, refactor as necessary for your app
    public static class MyService
        static List<string> AllData { get; set; }

        public static async Task<DataEnvelope<string>> GetItems(DataSourceRequest request)
            if (AllData == null)
                AllData = Enumerable.Range(1, 12345).Select(x => $"Name {x}").ToList();

            await Task.Delay(400); // simulate real network and database delays. Remove in a real app

            var result = await AllData.ToDataSourceResultAsync(request);
            DataEnvelope<string> dataToReturn = new DataEnvelope<string>
                Data = result.Data.Cast<string>().ToList(),
                Total = result.Total

            return await Task.FromResult(dataToReturn);

    // used to showcase how you could simplify the return of more than one value from the service
    public class DataEnvelope<T>
        public int Total { get; set; }
        public List<T> Data { get; set; }

See Also

In this article