New to Telerik UI for ASP.NET Core? Download free 30-day trial

Use MultiSelect as Filter in Grids

Environment

Product Progress® Telerik® UI MultiSelect for UI for ASP.NET Core

Description

How can I use a Telerik UI for ASP.NET Core MultiSelect as a filter in the Telerik UI for ASP.NET Core Grid?

Solution

  1. Configure the Grid Column Filterable UI API and pass the multiselectFilter() JavaScript function as a parameter.
  2. Implement the JavaScript function to disable the built-in filtration, define the MultiSelect dataSource, and extend the Grid’s dataSource filter() method.
  3. Define the removeFiltersForField() script to establish custom filtering logic.
  4. n the Controller, implement the filtering logic with the GetMultiSelectFilter() method and update the Read Action to support the MultiSelect filtering.
    @(Html.Kendo().Grid<ViewModel>()
        .Name("grid")
        .Columns(columns =>
        {
            columns.Bound(e => e.ID);
            columns.Bound(e => e.Tags).Filterable(filterable => filterable.Extra(false)
                    .Messages(m=> m.Info("Show items with value that contains"))
                    .UI("multiselectFilter")
                )
                .ClientTemplate("#:Tags.join(',')#");
        })
        .Filterable()
        .DataSource(dataSource => dataSource
            .Ajax()
            .Read(read => read.Action("Read", "Home"))
         )
    )
    @addTagHelper *, Kendo.Mvc

    <kendo-grid name="grid" >
        <datasource type="DataSourceTagHelperType.Ajax">
            <transport>
                <read url="@Url.Action("Read", "Home")" />
            </transport>
        </datasource>
        <columns>
            <column field="ID" title="Id" />
            <column field="Tags" title="Tags" template="#:Tags.join(',')#" >
                <filterable extra="false" filter-ui-handler="multiselectFilter">
                    <messages info="Show items with value that contains" />
                </filterable>
            </column>
        </columns>
        <filterable enabled="true" />
    </kendo-grid>
    <script>
        function multiselectFilter(element) {
            element.removeAttr("data-bind");
            var dataSource = $("#grid").data("kendoGrid").dataSource;
            var multiselect = element.kendoMultiSelect({
                dataSource: ["Tag1", "Tag2", "Tag3"]
            }).data("kendoMultiSelect");
            var form = element.closest("form");
            var popup = form.data("kendoPopup");
            form.find("[data-role=dropdownlist]").remove();

            form.find("[type='submit']").click(function (e) {
                e.preventDefault();
                e.stopPropagation();
                var filter = dataSource.filter() || { logic: "and", filters: [] };
                var tags = multiselect.value();
                removeFiltersForField(filter, "Tags");
                if (tags.length) {
                    filter.filters = filter.filters.concat($.map(tags, function (value) {
                        return {
                            operator: "eq",
                            value: value,
                            field: "Tags"
                        }
                    }));
                }
                dataSource.filter(filter);
                popup.close();
            }).end()
                .find("[type='reset']").click(function () {
                    multiselect.value([]);
                });
        }

        function removeFiltersForField(expression, field) {
            if (expression.filters) {
                expression.filters = $.grep(expression.filters, function (filter) {
                    removeFiltersForField(filter, field);
                    if (filter.filters) {
                        return filter.filters.length;
                    } else {
                        return filter.field != field;
                    }
                });
            }
        }
    </script>
    static List<ViewModel> data;
    static HomeController()
    {
        data = new List<ViewModel>()
        {
            new ViewModel
            {
                ID = 1,
                Tags = new List<string>(){"Tag1", "Tag2"}
            },
            new ViewModel
            {
                ID = 2,
                Tags = new List<string>(){"Tag2", "Tag3"}
            },
            new ViewModel
            {
                ID = 3,
                Tags = new List<string>(){"Tag3"}
            }
        };
    }

    public ActionResult Index()
    {
        ViewBag.Message = "Welcome to ASP.NET MVC!";

        return View();
    }

    private void GetMultiSelectFilter(IList<IFilterDescriptor> filters, List<object> result, String member)
    {
        for (int i = filters.Count - 1; i >= 0; i--)
        {
            var filter = filters[i];
            if (filter is CompositeFilterDescriptor)
            {
                GetMultiSelectFilter(((CompositeFilterDescriptor)filter).FilterDescriptors, result, member);
            }
            else if (((Kendo.Mvc.FilterDescriptor)filter).Member == member)
            {
                filters.Remove(filter);
                result.Add(((Kendo.Mvc.FilterDescriptor)filter).Value);
            }
        }
    }

    public ActionResult Read([DataSourceRequest] DataSourceRequest request)
    {
        List<object> tagFilters = new List<object>();
        GetMultiSelectFilter(request.Filters, tagFilters, "Tags");
        IQueryable<ViewModel> result = data.AsQueryable();
        if (tagFilters.Any())
        {
            result = result.Where(d => d.Tags.Any(t => tagFilters.Contains(t)));
        }

        return Json(result.ToDataSourceResult(request));
    }

For the complete implementation on how to use a Telerik UI for ASP.NET Core MultiSelect as a filter in the Telerik UI for ASP.NET Core Grid, refer to this GitHub project.

More ASP.NET Core Grid Resources

More ASP.NET Core MultiSelect Resources

See Also

In this article