From 641f7b0b797d96a8e0e873d8a8a4e54636a00e18 Mon Sep 17 00:00:00 2001 From: Vikram Reddy Date: Mon, 24 Mar 2025 22:23:39 +0530 Subject: [PATCH 1/2] Grid summary updates --- .../Grid_Demo_03_Change_Prefix.razor | 68 ++++++++++++++++++ .../Grid_Demo_04_Remove_Prefix.razor | 68 ++++++++++++++++++ .../Grid/16-summary/Grid_Demo_05_Locale.razor | 69 +++++++++++++++++++ .../Grid_Summary_Documentation.razor | 27 +++++++- blazorbootstrap/Components/Grid/Grid.razor | 2 +- blazorbootstrap/Components/Grid/Grid.razor.cs | 41 ++++++++--- .../Components/Grid/GridColumn.razor.cs | 11 +++ docs/docs/05-components/grid.mdx | 2 + 8 files changed, 275 insertions(+), 13 deletions(-) create mode 100644 BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_03_Change_Prefix.razor create mode 100644 BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_04_Remove_Prefix.razor create mode 100644 BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_05_Locale.razor diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_03_Change_Prefix.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_03_Change_Prefix.razor new file mode 100644 index 000000000..3e76c814c --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_03_Change_Prefix.razor @@ -0,0 +1,68 @@ + + + + + @context.Id + + + @context.Name + + + @context.Designation + + + @context.DOJ + + + @context.Salary.ToString("C") + + + @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 Employee { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), Salary = 7700, IsActive = true }, + new Employee { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), Salary = 19000, IsActive = true }, + new Employee { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), Salary = 12000, IsActive = true }, + new Employee { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), Salary = 19000, IsActive = false }, + new Employee { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), Salary = 16500.50f, IsActive = true }, + new Employee { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 24000, IsActive = true }, + new Employee { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 21000, IsActive = true }, + new Employee { Id = 113, Name = "Merlin", Designation = "Senior Consultant", DOJ = new DateOnly(1989, 10, 2), Salary = 13500, IsActive = true }, + new Employee { Id = 117, Name = "Sharna", Designation = "Data Analyst", DOJ = new DateOnly(1994, 5, 12), Salary = 15800.10f, IsActive = true }, + new Employee { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), Salary = 14000, IsActive = true }, + new Employee { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), Salary = 8000, IsActive = true }, + new Employee { Id = 111, Name = "Glenda", Designation = "Data Engineer", DOJ = new DateOnly(1994, 1, 12), Salary = 17850, IsActive = true }, + }; + } + + public record class Employee + { + public int Id { get; set; } + public string? Name { get; set; } + public string? Designation { get; set; } + public DateOnly DOJ { get; set; } + public float Salary { get; set; } + public bool IsActive { get; set; } + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_04_Remove_Prefix.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_04_Remove_Prefix.razor new file mode 100644 index 000000000..863972bce --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_04_Remove_Prefix.razor @@ -0,0 +1,68 @@ + + + + + @context.Id + + + @context.Name + + + @context.Designation + + + @context.DOJ + + + @context.Salary.ToString("C") + + + @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 Employee { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), Salary = 7700, IsActive = true }, + new Employee { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), Salary = 19000, IsActive = true }, + new Employee { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), Salary = 12000, IsActive = true }, + new Employee { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), Salary = 19000, IsActive = false }, + new Employee { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), Salary = 16500.50f, IsActive = true }, + new Employee { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 24000, IsActive = true }, + new Employee { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 21000, IsActive = true }, + new Employee { Id = 113, Name = "Merlin", Designation = "Senior Consultant", DOJ = new DateOnly(1989, 10, 2), Salary = 13500, IsActive = true }, + new Employee { Id = 117, Name = "Sharna", Designation = "Data Analyst", DOJ = new DateOnly(1994, 5, 12), Salary = 15800.10f, IsActive = true }, + new Employee { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), Salary = 14000, IsActive = true }, + new Employee { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), Salary = 8000, IsActive = true }, + new Employee { Id = 111, Name = "Glenda", Designation = "Data Engineer", DOJ = new DateOnly(1994, 1, 12), Salary = 17850, IsActive = true }, + }; + } + + public record class Employee + { + public int Id { get; set; } + public string? Name { get; set; } + public string? Designation { get; set; } + public DateOnly DOJ { get; set; } + public float Salary { get; set; } + public bool IsActive { get; set; } + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_05_Locale.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_05_Locale.razor new file mode 100644 index 000000000..eae7c5bb3 --- /dev/null +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_05_Locale.razor @@ -0,0 +1,69 @@ + + + + + @context.Id + + + @context.Name + + + @context.Designation + + + @context.DOJ + + + @context.Salary.ToString("C", System.Globalization.CultureInfo.GetCultureInfo("en-IN")) + + + @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 Employee { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), Salary = 7700, IsActive = true }, + new Employee { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), Salary = 19000, IsActive = true }, + new Employee { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), Salary = 12000, IsActive = true }, + new Employee { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), Salary = 19000, IsActive = false }, + new Employee { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), Salary = 16500.50f, IsActive = true }, + new Employee { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 24000, IsActive = true }, + new Employee { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 21000, IsActive = true }, + new Employee { Id = 113, Name = "Merlin", Designation = "Senior Consultant", DOJ = new DateOnly(1989, 10, 2), Salary = 13500, IsActive = true }, + new Employee { Id = 117, Name = "Sharna", Designation = "Data Analyst", DOJ = new DateOnly(1994, 5, 12), Salary = 15800.10f, IsActive = true }, + new Employee { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), Salary = 14000, IsActive = true }, + new Employee { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), Salary = 8000, IsActive = true }, + new Employee { Id = 111, Name = "Glenda", Designation = "Data Engineer", DOJ = new DateOnly(1994, 1, 12), Salary = 17850, IsActive = true }, + }; + } + + public record class Employee + { + public int Id { get; set; } + public string? Name { get; set; } + public string? Designation { get; set; } + public DateOnly DOJ { get; set; } + public float Salary { get; set; } + public bool IsActive { get; set; } + } +} \ No newline at end of file diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Summary_Documentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Summary_Documentation.razor index 362075568..a1b295729 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Summary_Documentation.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Summary_Documentation.razor @@ -26,12 +26,33 @@
- - NOTE: Summaries will be calculated based on the current page data. - +
+ Summaries will be calculated based on the current page data. +
+
+
+ Set the SummaryValuePrefix parameter to custom string to change the prefix from the summary value. +
+ +
+ +
+
+ Set the SummaryValuePrefix parameter to empty string to remove the prefix from the summary value. +
+ +
+ +
+
+ Set the Locale parameter on the Grid to change the CultureInfo of the summary. +
+ +
+ @code { private const string pageUrl = RouteConstants.Demos_Grid_Summary_Documentation; private const string pageTitle = "Blazor Grid - Summary"; diff --git a/blazorbootstrap/Components/Grid/Grid.razor b/blazorbootstrap/Components/Grid/Grid.razor index 41399356c..f3ceacba9 100644 --- a/blazorbootstrap/Components/Grid/Grid.razor +++ b/blazorbootstrap/Components/Grid/Grid.razor @@ -212,7 +212,7 @@ } else if (column.SummaryType != GridSummaryColumnType.None) { - @GetColumnSummaryValue(column.SummaryType, column.PropertyName, column.SummaryValueDisplayFormat) + @GetColumnSummaryValue(column.SummaryType, column.PropertyName, column.SummaryValueDisplayFormat, column.SummaryValuePrefix) } } } diff --git a/blazorbootstrap/Components/Grid/Grid.razor.cs b/blazorbootstrap/Components/Grid/Grid.razor.cs index 473713c42..51461dc0b 100644 --- a/blazorbootstrap/Components/Grid/Grid.razor.cs +++ b/blazorbootstrap/Components/Grid/Grid.razor.cs @@ -123,41 +123,40 @@ protected override Task OnParametersSetAsync() .Where(column => column.Filterable && column.GetFilterOperator() != FilterOperator.None && !string.IsNullOrWhiteSpace(column.GetFilterValue())) ?.Select(column => new FilterItem(column.PropertyName, column.GetFilterValue(), column.GetFilterOperator(), column.StringComparison)); - private string GetColumnSummaryValue(GridSummaryColumnType type, string propertyName, string format) + private string GetColumnSummaryValue(GridSummaryColumnType type, string propertyName, string format, string prefix) { - string? prefix = null; double value = 0; if (type == GridSummaryColumnType.Average) { - prefix = "Avg"; + prefix ??= "Avg: "; value = items?.Average(x => Convert.ToDouble(x.GetType().GetProperty(propertyName)?.GetValue(x))) ?? 0; } else if (type == GridSummaryColumnType.Count) { - prefix = "Count"; + prefix ??= "Count: "; value = items?.Where(x => x.GetType().GetProperty(propertyName)?.GetValue(x) is not null).Count() ?? 0; } else if (type == GridSummaryColumnType.Max) { - prefix = "Max"; + prefix ??= "Max: "; value = items?.Max(x => Convert.ToDouble(x.GetType().GetProperty(propertyName)?.GetValue(x))) ?? 0; } else if (type == GridSummaryColumnType.Min) { - prefix = "Min"; + prefix ??= "Min: "; value = items?.Min(x => Convert.ToDouble(x.GetType().GetProperty(propertyName)?.GetValue(x))) ?? 0; } else if (type == GridSummaryColumnType.Sum) { - prefix = "Total"; + prefix ??= "Total: "; value = items?.Sum(x => Convert.ToDouble(x.GetType().GetProperty(propertyName)?.GetValue(x))) ?? 0; } if (string.IsNullOrWhiteSpace(format)) - return $"{prefix}: {value}"; + return $"{prefix}{value}"; else - return $"{prefix}: {value.ToString(format)}"; + return $"{prefix}{value.ToString(format, GetCultureInfo())}"; } /// @@ -353,6 +352,21 @@ private RenderFragment ChildSelectionTemplate(int rowIndex, TItem rowData) => builder.CloseElement(); // close: th }; + private CultureInfo GetCultureInfo() + { + if (string.IsNullOrWhiteSpace(Locale)) + return CultureInfo.InvariantCulture; + + try + { + return CultureInfo.GetCultureInfo(Locale); + } + catch (CultureNotFoundException) + { + return CultureInfo.InvariantCulture; + } + } + private IEnumerable>? GetDefaultSorting() => !AllowSorting || columns == null || !columns.Any() ? null @@ -893,6 +907,15 @@ private void SetFilters(IEnumerable filterItems) //[EditorRequired] public string ItemsPerPageText { get; set; } = "Items per page"!; + /// + /// Gets or sets the locale. + /// + /// Default value is 'en-US'. + /// + /// + [Parameter] + public string? Locale { get; set; } = "en-US"; + /// /// This event is triggered when the user clicks on the row. /// Set AllowRowClick to true to enable row clicking. diff --git a/blazorbootstrap/Components/Grid/GridColumn.razor.cs b/blazorbootstrap/Components/Grid/GridColumn.razor.cs index aee83d14b..0c82529b4 100644 --- a/blazorbootstrap/Components/Grid/GridColumn.razor.cs +++ b/blazorbootstrap/Components/Grid/GridColumn.razor.cs @@ -512,6 +512,17 @@ private async Task OnSortClickAsync() [Parameter] public string? SummaryValueDisplayFormat { get; set; } + /// + /// Gets or sets the summary value prefix. If set, it will be displayed before the summary value. + /// Otherwise, based on the , default prefix will be displayed. + /// To remove the default prefix, set this property to an empty string. + /// + /// Example: "Total: ", "Average: ", etc. + /// + /// + [Parameter] + public string? SummaryValuePrefix { get; set; } + /// /// Gets or sets the text alignment. /// diff --git a/docs/docs/05-components/grid.mdx b/docs/docs/05-components/grid.mdx index ea8e9a0e2..f280473a4 100644 --- a/docs/docs/05-components/grid.mdx +++ b/docs/docs/05-components/grid.mdx @@ -44,6 +44,7 @@ Use Blazor Bootstrap grid component to display tabular data from the data source | HeaderRowCssClass | string | null | | Gets or sets the header row css class but not the thead tag class. | 1.9.2 | | Height | float | 320 pixels | | Gets or sets the grid height. | 1.10.3 | | ItemsPerPageText | string | `Items per page` | ✔️ | Gets or sets the items per page text. | 1.9.5 | +| Locale | string? | `en-US` | | Gets or sets the locale. Default value is 'en-US'. | 3.4.0 | | PageSize | int | 10 | | Gets or sets the page size. | 1.0.0 | | PageSizeSelectorItems | `int[]` | `new int[] { 10, 20, 50 }` | ✔️ | Gets or sets the page size selector items. | 1.8.0 | | PageSizeSelectorVisible | bool | false | | Gets or sets the page size selector visible. | 1.8.0 | @@ -103,6 +104,7 @@ Grid requires either `Data` or `DataProvider` parameter, but not both. | StringComparison | `StringComparison` | `StringComparison.OrdinalIgnoreCase` | | Gets or sets the StringComparison. Use `StringComparison.CurrentCulture` or `StringComparison.CurrentCultureIgnoreCase` or `StringComparison.InvariantCulture` or `StringComparison.InvariantCultureIgnoreCase` or `StringComparison.Ordinal` or `StringComparison.OrdinalIgnoreCase`. | 1.0.0 | | SummaryType | `GridSummaryColumnType` | `GridSummaryColumnType.None` | | Gets or sets the summary type. Supported values are `GridSummaryColumnType.None`, `GridSummaryColumnType.Count`, `GridSummaryColumnType.Sum`, `GridSummaryColumnType.Average`, `GridSummaryColumnType.Min`, `GridSummaryColumnType.Max`. | 3.4.0 | | SummaryValueDisplayFormat | string | null | | Gets or sets the summary value display format. | 3.4.0 | +| SummaryValuePrefix | string | null | | Gets or sets the summary value prefix. If set, it will be displayed before the summary value. Otherwise, based on the , default prefix will be displayed. To remove the default prefix, set this property to an empty string. | 3.4.0 | | TextAlignment | `Alignment` | `Alignment.Start` | | Gets or sets the text alignment. Use `Alignment.Start` or `Alignment.Center` or `Alignment.End`. | 1.0.0 | | TextNoWrap | bool | false | | Gets or sets text nowrap. | 1.0.0 | | IsVisible | bool | true | | Gets or sets visibility of the Grid column. | 3.4.0 | From ff9fbd2c7b93e00aed207b96402d068cc3ab7024 Mon Sep 17 00:00:00 2001 From: Vikram Reddy Date: Mon, 24 Mar 2025 22:26:06 +0530 Subject: [PATCH 2/2] Demos - updated --- .../Pages/Grid/16-summary/Grid_Demo_01_Summary_Example.razor | 2 +- .../16-summary/Grid_Demo_02_Summary_with_Filters_Paging.razor | 2 +- .../Pages/Grid/16-summary/Grid_Demo_03_Change_Prefix.razor | 2 +- .../Pages/Grid/16-summary/Grid_Demo_04_Remove_Prefix.razor | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_01_Summary_Example.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_01_Summary_Example.razor index 06d260920..a98ce4b5b 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_01_Summary_Example.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_01_Summary_Example.razor @@ -17,7 +17,7 @@ @context.DOJ - + @context.Salary.ToString("C") diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_02_Summary_with_Filters_Paging.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_02_Summary_with_Filters_Paging.razor index 74d65d11c..103638ed1 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_02_Summary_with_Filters_Paging.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_02_Summary_with_Filters_Paging.razor @@ -24,7 +24,7 @@ @context.DOJ - + @context.Salary.ToString("C") diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_03_Change_Prefix.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_03_Change_Prefix.razor index 3e76c814c..5635a7ebb 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_03_Change_Prefix.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_03_Change_Prefix.razor @@ -17,7 +17,7 @@ @context.DOJ - + @context.Salary.ToString("C") diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_04_Remove_Prefix.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_04_Remove_Prefix.razor index 863972bce..9c8a1039c 100644 --- a/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_04_Remove_Prefix.razor +++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_04_Remove_Prefix.razor @@ -17,7 +17,7 @@ @context.DOJ - + @context.Salary.ToString("C")