From b4e11bf08fbd72753aae709085ccb31eac851ee1 Mon Sep 17 00:00:00 2001 From: RKUZNETSOV Date: Thu, 6 Nov 2025 10:30:45 +0300 Subject: [PATCH] Added support for custom column filter templates --- .../Grid_Demo_07_Custom_Filter_Template.razor | 61 +++++++++++++++++++ .../Grid_Filters_Documentation.razor | 4 ++ .../Grid/03-filters/StatusSelector.razor | 24 ++++++++ blazorbootstrap/Components/Grid/Grid.razor | 15 +---- .../Components/Grid/GridColumn.razor | 24 ++++++++ .../Components/Grid/GridColumn.razor.cs | 14 ++++- .../Models/GridColumnFilterContext.cs | 5 ++ .../Models/GridColumnFilterRenderContext.cs | 5 ++ 8 files changed, 138 insertions(+), 14 deletions(-) create mode 100644 BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Demo_07_Custom_Filter_Template.razor create mode 100644 BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/StatusSelector.razor create mode 100644 blazorbootstrap/Models/GridColumnFilterContext.cs create mode 100644 blazorbootstrap/Models/GridColumnFilterRenderContext.cs diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Demo_07_Custom_Filter_Template.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Demo_07_Custom_Filter_Template.razor new file mode 100644 index 000000000..fab2e7f4b --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Demo_07_Custom_Filter_Template.razor @@ -0,0 +1,61 @@ + + + + + @context.Id + + + @context.Name + + + @context.Designation + + + @context.DOJ + + + + + + + @context.IsActive + + + + + + +@code { + private IEnumerable employees = default!; + + private async Task> EmployeesDataProvider(GridDataProviderRequest request) + { + if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging + employees = GetEmployees(); // call a service or an API to pull the employees + + return await Task.FromResult(request.ApplyTo(employees)); + } + + private IEnumerable GetEmployees() + { + return new List + { + new Employee4 { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), IsActive = true }, + new Employee4 { Id = null, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), IsActive = true }, + new Employee4 { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), IsActive = true }, + new Employee4 { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), IsActive = false }, + new Employee4 { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), IsActive = true }, + new Employee4 { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true }, + new Employee4 { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), IsActive = true }, + new Employee4 { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), IsActive = true }, + new Employee4 { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = null, IsActive = true }, + new Employee4 { Id = 110, Name = "Vijay", Designation = null, DOJ = new DateOnly(1990, 7, 1), IsActive = true }, + }; + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Filters_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Filters_Documentation.razor index 5b2854421..6012fc4ca 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Filters_Documentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/Grid_Filters_Documentation.razor @@ -65,6 +65,10 @@ +
+ +
+ @code { private const string pageUrl = RouteConstants.Demos_Grid_Filters_Documentation; private const string pageTitle = "Blazor Grid - Filters"; diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/StatusSelector.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/StatusSelector.razor new file mode 100644 index 000000000..9c7dc9b35 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/03-filters/StatusSelector.razor @@ -0,0 +1,24 @@ +@if (Value == VALUE_TRUE) +{ + +} +else if (Value == VALUE_FALSE) +{ + +} +else +{ + +} + +@code { + private const string VALUE_FALSE = "False"; + private const string VALUE_TRUE = "True"; + private const string VALUE_EMPTY = ""; + + [Parameter] + public string? Value { get; set; } + + [Parameter] + public EventCallback ValueChanged { get; set; } +} diff --git a/blazorbootstrap/Components/Grid/Grid.razor b/blazorbootstrap/Components/Grid/Grid.razor index 61b311dc6..15fa8fa3c 100644 --- a/blazorbootstrap/Components/Grid/Grid.razor +++ b/blazorbootstrap/Components/Grid/Grid.razor @@ -1,4 +1,5 @@ @namespace BlazorBootstrap +@using BlazorBootstrap.Models @inherits BlazorBootstrapComponentBase @typeparam TItem @@ -35,6 +36,7 @@ @if (AllowFiltering) { + var columnFilterContext = new GridColumnFilterContext(EnumFilterSelectText, GridFiltersTranslationProviderAsync!, FixedHeader); @if (AllowDetailView) { @@ -70,18 +72,7 @@ @if (column.Filterable) { - + @column.RenderColumnFilter(columnFilterContext) } } diff --git a/blazorbootstrap/Components/Grid/GridColumn.razor b/blazorbootstrap/Components/Grid/GridColumn.razor index 1674383a5..6c0cb2a66 100644 --- a/blazorbootstrap/Components/Grid/GridColumn.razor +++ b/blazorbootstrap/Components/Grid/GridColumn.razor @@ -1,3 +1,27 @@ @namespace BlazorBootstrap +@using BlazorBootstrap.Models @inherits BlazorBootstrapComponentBase @typeparam TItem + +@code{ + internal RenderFragment RenderColumnFilter(GridColumnFilterContext context) + { + if (CustomColumnFilter is not null) + { + return CustomColumnFilter(new(context, this)); + } + + return @; + } +} \ No newline at end of file diff --git a/blazorbootstrap/Components/Grid/GridColumn.razor.cs b/blazorbootstrap/Components/Grid/GridColumn.razor.cs index 0c82529b4..d83eb257b 100644 --- a/blazorbootstrap/Components/Grid/GridColumn.razor.cs +++ b/blazorbootstrap/Components/Grid/GridColumn.razor.cs @@ -1,4 +1,6 @@ -namespace BlazorBootstrap; +using BlazorBootstrap.Models; + +namespace BlazorBootstrap; public partial class GridColumn : BlazorBootstrapComponentBase { @@ -60,7 +62,7 @@ internal IEnumerable> GetSorting() yield return new SortingItem(SortString, SortKeySelector!, currentSortDirection); } - internal async Task OnFilterChangedAsync(FilterEventArgs args, GridColumn column) + public async Task OnFilterChangedAsync(FilterEventArgs args) { if (filterValue != args.Text || filterOperator != args.FilterOperator) await Parent.ResetPageNumberAsync(); @@ -203,6 +205,12 @@ private async Task OnSortClickAsync() [Parameter] public RenderFragment ChildContent { get; set; } = default!; + /// + /// Specifies the content of custom column filter + /// + [Parameter] + public RenderFragment>? CustomColumnFilter { get; set; } + /// /// Gets or sets the column class. /// @@ -273,6 +281,8 @@ private async Task OnSortClickAsync() [Parameter] public string FilterValue { get; set; } = default!; + public string ActualFilterValue => filterValue; + /// /// Indicates whether the column is frozen. /// diff --git a/blazorbootstrap/Models/GridColumnFilterContext.cs b/blazorbootstrap/Models/GridColumnFilterContext.cs new file mode 100644 index 000000000..b90f8056a --- /dev/null +++ b/blazorbootstrap/Models/GridColumnFilterContext.cs @@ -0,0 +1,5 @@ +namespace BlazorBootstrap.Models; + +public sealed record GridColumnFilterContext(string? EnumFilterSelectText, GridFiltersTranslationDelegate FiltersTranslationProvider, bool FixedHeader) +{ +} diff --git a/blazorbootstrap/Models/GridColumnFilterRenderContext.cs b/blazorbootstrap/Models/GridColumnFilterRenderContext.cs new file mode 100644 index 000000000..465287cf6 --- /dev/null +++ b/blazorbootstrap/Models/GridColumnFilterRenderContext.cs @@ -0,0 +1,5 @@ +namespace BlazorBootstrap.Models; + +public sealed record GridColumnFilterRenderContext(GridColumnFilterContext GridContext, GridColumn Column) +{ +}