Dynamically filtering multiselect datasource on item select/ValueChange

@page "/"
<h3>TestMs</h3>


<SfMultiSelect TItem="Order" @ref="MSOrders" EnableChangeOnBlur="false" TValue="List<string>" DataSource="@filteredOrders"
               Placeholder="Select an order" AllowFiltering="true">
    <MultiSelectEvents TItem="Order" TValue="List<string>" ValueChange="OnValueChange"
     ></MultiSelectEvents>
    <MultiSelectFieldSettings Text="Name" Value="Id"></MultiSelectFieldSettings>
</SfMultiSelect>


@code {
    List<Order> orders = GenerateOrders(50);
    List<Order> filteredOrders { get; set; }
    SfMultiSelect<List<String>, Order> MSOrders { get; set; }
    protected override async Task OnInitializedAsync()
    {
        filteredOrders = new(orders);


    }


    public class Order
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Valid { get; set; }
    }


    static List<Order> GenerateOrders(int count)
    {
        List<Order> generatedOrders = new List<Order>();
        Random random = new Random();


        for (int i = 1; i <= count; i++)
        {
            Order order = new Order
                {
                    Id = i,
                    Name = "Order " + i,
                    Valid = random.Next(0, 2)
                };


            generatedOrders.Add(order);
        }


        return generatedOrders;
    }


    private void OnValueChange(Syncfusion.Blazor.DropDowns.MultiSelectChangeEventArgs<List<string>> args)
    {
        filteredOrders.Clear();
        if (args?.Value?.Count > 0)
        {
            int selectedOrderId = int.Parse(args.Value[0]);
            Order selectedOrder = orders.FirstOrDefault(o => o.Id == selectedOrderId);
            if (selectedOrder != null)
            {
                filteredOrders.AddRange (orders.Where(o => o.Valid == selectedOrder.Valid).ToList());
                MSOrders.FilterAsync(filteredOrders);
             }
        }
        else
        {
            filteredOrders.AddRange(orders);
        }
    }
}

Once an item is picked, I want the datasource list to be filtered based on some property of the picked item. I have managed to achieve this partly, but when I use  MSOrders.FilterAsync(filteredOrders);after that the filtering doesn't work at all. Also if I first filter and then select an item, the list doesn't get filtered either.




1 Reply

YS Yohapuja Selvakumaran Syncfusion Team April 5, 2024 01:17 PM UTC

Hi Big Gucci,


Thank you for reaching out to us. We've diligently reviewed your requirement and successfully addressed it by implementing custom filtering. Now, after updating the datasource, the filtering functionality works seamlessly.


Below is the modified code snippet:


<SfMultiSelect TItem="Order" @ref="MSOrders" EnableChangeOnBlur="false" TValue="List<string>" DataSource="@filteredOrders"

               Placeholder="Select an order" AllowFiltering="true">

    <MultiSelectEvents TItem="Order" TValue="List<string>" ValueChange="OnValueChange" Filtering="OnFilter"></MultiSelectEvents>

    <MultiSelectFieldSettings Text="Name" Value="Id"></MultiSelectFieldSettings>

</SfMultiSelect>

 

 

@code {

    List<Order> orders = GenerateOrders(50);

    List<Order> filteredOrders { get; set; }

    SfMultiSelect<List<String>, Order> MSOrders { get; set; }

    protected override async Task OnInitializedAsync()

    {

        filteredOrders = new(orders);

 

 

    }

 

 

    public class Order

    {

        public int Id { get; set; }

        public string Name { get; set; }

        public int Valid { get; set; }

    }

 

 

    static List<Order> GenerateOrders(int count)

    {

        List<Order> generatedOrders = new List<Order>();

        Random random = new Random();

 

 

        for (int i = 1; i <= count; i++)

        {

            Order order = new Order

                {

                    Id = i,

                    Name = "Order " + i,

                    Valid = random.Next(0, 2)

                };

 

 

            generatedOrders.Add(order);

        }

 

 

        return generatedOrders;

    }

 

 

    private void OnValueChange(Syncfusion.Blazor.DropDowns.MultiSelectChangeEventArgs<List<string>> args)

    {

        filteredOrders.Clear();

        if (args?.Value?.Count > 0)

        {

            int selectedOrderId = int.Parse(args.Value[0]);

            Order selectedOrder = orders.FirstOrDefault(o => o.Id == selectedOrderId);

            if (selectedOrder != null)

            {

                filteredOrders.AddRange(orders.Where(o => o.Valid == selectedOrder.Valid).ToList());

                MSOrders.FilterAsync(filteredOrders);

            }

        }

        else

        {

            filteredOrders.AddRange(orders);

        }

    }

 

    private async Task OnFilter(FilteringEventArgs args)

    {

        args.PreventDefaultAction = true;

        var query = new Query().Where(new WhereFilter() { Field = "Name", Operator = "contains", value = args.Text, IgnoreCase = true });

 

        query = !string.IsNullOrEmpty(args.Text) ? query : new Query();

 

        await MSOrders.FilterAsync(filteredOrders, query);

    }

}



For further reference and to see the changes in action, please visit the provided sample link:


Sample: https://blazorplayground.syncfusion.com/BXhJDJDSfRfTwiqh


For further information about custom filtering and to explore more options, kindly refer to our documentation:


Documentation: https://blazor.syncfusion.com/documentation/multiselect-dropdown/filtering#custom-filtering




Regards,

Yohapuja S


Loader.
Up arrow icon