Virtualization in Blazor MultiSelect Dropdown Component

12 Jun 202420 minutes to read

The MultiSelect component includes a virtual scrolling feature designed to enhance UI performance, particularly for handling large datasets. By enabling the EnableVirtualization option, the MultiSelect intelligently manages data rendering, ensuring only a subset of items is initially loaded when the component is rendered. As you interact with the dropdown, additional items are dynamically loaded as you scroll, creating a smooth and efficient user experience.

This feature is applicable to both local and remote data scenarios, providing flexibility in its implementation. For instance, consider a case where the MultiSelect is bound to a dataset containing 150 items. Upon opening the dropdown, only a few items are loaded initially, based on the height of the popup. As you scroll through the list, additional items are fetched and loaded on-demand, allowing you to effortlessly explore the complete dataset.

Binding local data

The MultiSelect component can generate its list items through an array of complex data. For this, the appropriate columns should be mapped to the fields property. When using virtual scrolling, the list updates based on the scroll offset value, triggering a request to fetch more data from the server.

In the following example, ID column and Text column from complex data have been mapped to the Value field and Text field, respectively.

@using Syncfusion.Blazor.DropDowns
@using Syncfusion.Blazor.Data 

<SfMultiSelect TValue="string[]" TItem="Record" Placeholder="Select an item" DataSource="@Records" Query="@LocalDataQuery" AllowFiltering="true" PopupHeight="160px" EnableVirtualization="true">
    <MultiSelectFieldSettings Text="Text" Value="ID"></MultiSelectFieldSettings>
</SfMultiSelect>

@code{
    public Query LocalDataQuery = new Query().Take(6); 
    public class Record 
    { 
        public string ID { get; set; } 
        public string Text { get; set; } 
    } 
    public List<Record> Records { get; set; } 
    protected override void OnInitialized()
    { 
        this.Records = Enumerable.Range(1, 150).Select(i => new Record() 
        { 
            ID = i.ToString(), 
            Text = "Item " + i, 
        }).ToList(); 
    } 
}

Binding remote data

The MultiSelect supports retrieval of data from remote data services with the help of DataManager component. When using remote data, it initially fetches all the data from the server, triggering the ActionBegin and ActionComplete events, and then stores the data locally. During virtual scrolling, additional data is retrieved from the locally stored data, triggering the ActionBegin and ActionComplete events at that time as well.

The following sample displays the EmployeeID from the VirtualDropdownData Data Service.

  • RAZOR
  • @using Syncfusion.Blazor.DropDowns
    @using Syncfusion.Blazor.Data 
    
    <SfMultiSelect TValue="string[]" TItem="OrderDetails" AllowFiltering="true" PopupHeight="160px" EnableVirtualization="true" Placeholder="Select ID" Query="@RemoteDataQuery">
        <SfDataManager Url="https://services.syncfusion.com/js/production/api/VirtualDropdownData" CrossDomain="true" Adaptor="Syncfusion.Blazor.Adaptors.UrlAdaptor" />
        <MultiSelectFieldSettings Text="EmployeeID" Value="EmployeeID" />
    </SfMultiSelect>
    
    @code{
        public Query RemoteDataQuery = new Query().Take(6); 
        public class OrderDetails
        {
            public int? OrderID { get; set; }
            public string CustomerID { get; set; }
            public string EmployeeID { get; set; }
            public double? Freight { get; set; }
            public string ShipCity { get; set; }
            public bool Verified { get; set; }
            public DateTime? OrderDate { get; set; }
            public string ShipName { get; set; }
            public string ShipCountry { get; set; }
            public DateTime? ShippedDate { get; set; }
            public string ShipAddress { get; set; }
        }
    }

    Customizing items count in virtualization

    When the EnableVirtualization property is enabled, the Take property provided by the user within the Query parameter at the initial state or during the ActionBegin event will be considered. Internally, it calculates the items that fit onto the current page (i.e., probably twice the amount of the popup’s height). If the user-provided take value is less than the minimum number of items that fit into the popup, the user-provided take value will not be considered.

    The following sample shows the example for Customizing items count in virtualization.

  • RAZOR
  • @using Syncfusion.Blazor.DropDowns
    @using Syncfusion.Blazor.Data 
    
    <SfMultiSelect TValue="string[]" TItem="Record" Placeholder="e.g. Item 1" DataSource="@Records" Query="@LocalDataQuery" AllowFiltering="true" PopupHeight="160px" EnableVirtualization="true">
        <MultiSelectFieldSettings Text="Text" Value="ID"></MultiSelectFieldSettings>
    </SfMultiSelect>
    
    @code{
       public Query LocalDataQuery = new Query().Take(25);
       public class Record 
        { 
            public string ID { get; set; } 
            public string Text { get; set; } 
            public string Group { get; set; }
        } 
        public List<Record> Records { get; set; } 
        protected override void OnInitialized()
        {
            var random = new Random();
            this.Records = Enumerable.Range(1, 150).Select(i => new Record()
                {
                    ID = i.ToString(),
                    Text = "Item " + i,
                    Group = GetRandomGroup(random)
                }).ToList();
        }
        private string GetRandomGroup(Random random)
        {
            switch (random.Next(1, 5))
            {
                case 1:
                    return "Group A";
                case 2:
                    return "Group B";
                case 3:
                    return "Group C";
                case 4:
                    return "Group D";
                default:
                    return string.Empty;
            }
        }
    }

    Grouping with virtualization

    The MultiSelect component supports grouping with Virtualization. It allows you to organize elements into groups based on different categories. Each item in the list can be classified using the GroupBy field in the data table. After grouping, virtualization works similarly to local data binding, providing a seamless user experience. When the data source is bound to remote data, an initial request is made to retrieve all data for the purpose of grouping. Subsequently, the grouped data works in the same way as local data binding on virtualization.

    The following sample shows the example for Grouping with Virtualization.

  • RAZOR
  • @using Syncfusion.Blazor.DropDowns
    @using Syncfusion.Blazor.Data 
    
    <SfMultiSelect TValue="string[]" TItem="Record" Placeholder="e.g. Item 1" DataSource="@Records" Query="@LocalDataQuery" AllowFiltering="true" PopupHeight="160px" EnableVirtualization="true">
        <MultiSelectFieldSettings GroupBy="Group" Text="Text" Value="ID"></MultiSelectFieldSettings>
    </SfMultiSelect>
    
    @code{
       public Query LocalDataQuery = new Query().Take(10);
       public class Record 
        { 
            public string ID { get; set; } 
            public string Text { get; set; } 
            public string Group { get; set; }
        } 
        public List<Record> Records { get; set; } 
        protected override void OnInitialized()
        {
            var random = new Random();
            this.Records = Enumerable.Range(1, 150).Select(i => new Record()
                {
                    ID = i.ToString(),
                    Text = "Item " + i,
                    Group = GetRandomGroup(random)
                }).ToList();
        }
        private string GetRandomGroup(Random random)
        {
            switch (random.Next(1, 5))
            {
                case 1:
                    return "Group A";
                case 2:
                    return "Group B";
                case 3:
                    return "Group C";
                case 4:
                    return "Group D";
                default:
                    return string.Empty;
            }
        }
    }

    Filtering with virtualization

    The MultiSelect component supports Filtering with Virtualization. The MultiSelect includes a built-in feature that enables data filtering when the AllowFiltering option is enabled. In the context of Virtual Scrolling, the filtering process operates in response to the typed characters. Specifically, the MultiSelect sends a request to the server, utilizing the full data source, to achieve filtering. Before initiating the request, an action event is triggered. Upon successful retrieval of data from the server, an action complete event is triggered. The initial data is loaded when the popup is opened. Whether the filter list has a selection or not, the popup closes.

    The following sample shows the example for Filtering with Virtualization.

  • RAZOR
  • @using Syncfusion.Blazor.DropDowns
    @using Syncfusion.Blazor.Data 
    
    <SfMultiSelect TValue="string[]" TItem="Record" Placeholder="e.g. Item 1" DataSource="@Records" Query="@LocalDataQuery" AllowFiltering="true" PopupHeight="160px" EnableVirtualization="true">
        <MultiSelectFieldSettings Text="Text" Value="ID"></MultiSelectFieldSettings>
    </SfMultiSelect>
    
    @code{
       public Query LocalDataQuery = new Query().Take(10);
       public class Record 
        { 
            public string ID { get; set; } 
            public string Text { get; set; } 
            public string Group { get; set; }
        } 
        public List<Record> Records { get; set; } 
        protected override void OnInitialized()
        {
            var random = new Random();
            this.Records = Enumerable.Range(1, 150).Select(i => new Record()
                {
                    ID = i.ToString(),
                    Text = "Item " + i,
                    Group = GetRandomGroup(random)
                }).ToList();
        }
        private string GetRandomGroup(Random random)
        {
            switch (random.Next(1, 5))
            {
                case 1:
                    return "Group A";
                case 2:
                    return "Group B";
                case 3:
                    return "Group C";
                case 4:
                    return "Group D";
                default:
                    return string.Empty;
            }
        }
    }

    Checkbox with virtualization

    The MultiSelect component supports CheckBox selection with Virtualization. The MultiSelect comes with integrated functionality that allows for the selection of multiple values using checkboxes when the Mode property is configured to CheckBox. In the context of Virtual Scrolling, the checkbox render with each list element. based on the checkbox selection and unselection, component value property updated with respective values.

    The following sample shows the example for checkbox with Virtualization.

  • RAZOR
  • @using Syncfusion.Blazor.DropDowns
    @using Syncfusion.Blazor.Data 
    
    <SfMultiSelect TValue="string[]" TItem="Record" Placeholder="e.g. Item 1" DataSource="@Records" Query="@LocalDataQuery" AllowFiltering="true" PopupHeight="160px" Mode="VisualMode.CheckBox" EnableVirtualization="true">
        <MultiSelectFieldSettings Text="Text" Value="ID"></MultiSelectFieldSettings>
    </SfMultiSelect>
    
    @code{
       public Query LocalDataQuery = new Query().Take(10);
       public class Record 
        { 
            public string ID { get; set; } 
            public string Text { get; set; } 
            public string Group { get; set; }
        } 
        public List<Record> Records { get; set; } 
        protected override void OnInitialized()
        {
            var random = new Random();
            this.Records = Enumerable.Range(1, 150).Select(i => new Record()
                {
                    ID = i.ToString(),
                    Text = "Item " + i,
                    Group = GetRandomGroup(random)
                }).ToList();
        }
        private string GetRandomGroup(Random random)
        {
            switch (random.Next(1, 5))
            {
                case 1:
                    return "Group A";
                case 2:
                    return "Group B";
                case 3:
                    return "Group C";
                case 4:
                    return "Group D";
                default:
                    return string.Empty;
            }
        }
    }

    Custom value with virtualization

    The MultiSelect component supports custom value with Virtualization. When the AllowCustomValue property is enabled, the MultiSelect enables users to include a new option not currently available in the component value. Upon selecting this newly added custom value, the MultiSelect triggers the CustomValueSpecifier event and also custom value will be added to the end of the complete list.

    The following sample shows the example for custom value with Virtualization.

  • RAZOR
  • @using Syncfusion.Blazor.DropDowns
    @using Syncfusion.Blazor.Data 
    
    <SfMultiSelect TValue="string[]" TItem="Record" Placeholder="e.g. Item 1" DataSource="@Records" Query="@LocalDataQuery" AllowFiltering="true" AllowCustomValue="true" PopupHeight="160px" EnableVirtualization="true">
        <MultiSelectFieldSettings Text="Text" Value="ID"></MultiSelectFieldSettings>
    </SfMultiSelect>
    
    @code{
       public Query LocalDataQuery = new Query().Take(10);
       public class Record 
        { 
            public string ID { get; set; } 
            public string Text { get; set; } 
            public string Group { get; set; }
        } 
        public List<Record> Records { get; set; } 
        protected override void OnInitialized()
        {
            var random = new Random();
            this.Records = Enumerable.Range(1, 150).Select(i => new Record()
                {
                    ID = i.ToString(),
                    Text = "Item " + i,
                    Group = GetRandomGroup(random)
                }).ToList();
        }
        private string GetRandomGroup(Random random)
        {
            switch (random.Next(1, 5))
            {
                case 1:
                    return "Group A";
                case 2:
                    return "Group B";
                case 3:
                    return "Group C";
                case 4:
                    return "Group D";
                default:
                    return string.Empty;
            }
        }
    }

    Preselect values with virtualization

    The MultiSelect component extends its support for preselected values with Virtualization. When binding values from local or remote data to the MultiSelect component, the corresponding data value is fetched from the server and promptly updated within the component. Moreover, when binding a custom value to the component, the value is updated within the component, and the bound custom value is seamlessly appended to the end of the complete list.

    The following sample shows the example for Preselect value with Virtualization.

  • RAZOR
  • @using Syncfusion.Blazor.DropDowns
    @using Syncfusion.Blazor.Data 
    
    <SfMultiSelect TValue="string[]" TItem="Record" Placeholder="e.g. Item 1" @bind-Value="@Value" DataSource="@Records" Query="@LocalDataQuery" AllowFiltering="true" PopupHeight="160px" EnableVirtualization="true">
        <MultiSelectFieldSettings Text="Text" Value="ID"></MultiSelectFieldSettings>
    </SfMultiSelect>
    
    @code{
       public Query LocalDataQuery = new Query().Take(10);
       public string[] Value { get; set; } = new string[] { "10", "50", "100" };
       public class Record 
        { 
            public string ID { get; set; } 
            public string Text { get; set; } 
            public string Group { get; set; }
        } 
        public List<Record> Records { get; set; } 
        protected override void OnInitialized()
        {
            var random = new Random();
            this.Records = Enumerable.Range(1, 150).Select(i => new Record()
                {
                    ID = i.ToString(),
                    Text = "Item " + i,
                    Group = GetRandomGroup(random)
                }).ToList();
        }
        private string GetRandomGroup(Random random)
        {
            switch (random.Next(1, 5))
            {
                case 1:
                    return "Group A";
                case 2:
                    return "Group B";
                case 3:
                    return "Group C";
                case 4:
                    return "Group D";
                default:
                    return string.Empty;
            }
        }
    }