Skip to content

Commit 41859ad

Browse files
authored
Grid summary updates (#1072)
* Grid summary updates
1 parent 7322966 commit 41859ad

File tree

10 files changed

+277
-15
lines changed

10 files changed

+277
-15
lines changed

BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_01_Summary_Example.razor

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<GridColumn TItem="Employee" HeaderText="DOJ" PropertyName="DOJ">
1818
@context.DOJ
1919
</GridColumn>
20-
<GridColumn TItem="Employee" HeaderText="Salary" PropertyName="Salary" SummaryType="GridSummaryColumnType.Sum" SummaryValueDisplayFormat="C">
20+
<GridColumn TItem="Employee" HeaderText="Salary" HeaderTextAlignment="Alignment.End" TextAlignment="Alignment.End" PropertyName="Salary" SummaryType="GridSummaryColumnType.Sum" SummaryValueDisplayFormat="C">
2121
@context.Salary.ToString("C")
2222
</GridColumn>
2323
<GridColumn TItem="Employee" HeaderText="Active" PropertyName="IsActive">

BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Demo_02_Summary_with_Filters_Paging.razor

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
<GridColumn TItem="Employee" HeaderText="DOJ" PropertyName="DOJ" SortKeySelector="item => item.DOJ">
2525
@context.DOJ
2626
</GridColumn>
27-
<GridColumn TItem="Employee" HeaderText="Salary" PropertyName="Salary" SortKeySelector="item => item.Salary" SummaryType="GridSummaryColumnType.Sum" SummaryValueDisplayFormat="C">
27+
<GridColumn TItem="Employee" HeaderText="Salary" HeaderTextAlignment="Alignment.End" TextAlignment="Alignment.End" PropertyName="Salary" SortKeySelector="item => item.Salary" SummaryType="GridSummaryColumnType.Sum" SummaryValueDisplayFormat="C">
2828
@context.Salary.ToString("C")
2929
</GridColumn>
3030
<GridColumn TItem="Employee" HeaderText="Active" PropertyName="IsActive" SortKeySelector="item => item.IsActive">
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<Grid TItem="Employee"
2+
Class="table table-hover table-bordered table-striped"
3+
DataProvider="EmployeesDataProvider"
4+
AllowSummary="true"
5+
Responsive="true">
6+
7+
<GridColumns>
8+
<GridColumn TItem="Employee" HeaderText="Id" PropertyName="Id">
9+
@context.Id
10+
</GridColumn>
11+
<GridColumn TItem="Employee" HeaderText="Employee Name" PropertyName="Name" SummaryType="GridSummaryColumnType.Count" SummaryValuePrefix="Records count: ">
12+
@context.Name
13+
</GridColumn>
14+
<GridColumn TItem="Employee" HeaderText="Designation" PropertyName="Designation">
15+
@context.Designation
16+
</GridColumn>
17+
<GridColumn TItem="Employee" HeaderText="DOJ" PropertyName="DOJ">
18+
@context.DOJ
19+
</GridColumn>
20+
<GridColumn TItem="Employee" HeaderText="Salary" HeaderTextAlignment="Alignment.End" TextAlignment="Alignment.End" PropertyName="Salary" SummaryType="GridSummaryColumnType.Sum" SummaryValueDisplayFormat="C" SummaryValuePrefix="Sum: ">
21+
@context.Salary.ToString("C")
22+
</GridColumn>
23+
<GridColumn TItem="Employee" HeaderText="Active" PropertyName="IsActive">
24+
@context.IsActive
25+
</GridColumn>
26+
</GridColumns>
27+
</Grid>
28+
29+
@code {
30+
private IEnumerable<Employee> employees = default!;
31+
32+
private async Task<GridDataProviderResult<Employee>> EmployeesDataProvider(GridDataProviderRequest<Employee> request)
33+
{
34+
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
35+
employees = GetEmployees(); // call a service or an API to pull the employees
36+
37+
return await Task.FromResult(request.ApplyTo(employees));
38+
}
39+
40+
private IEnumerable<Employee> GetEmployees()
41+
{
42+
return new List<Employee>
43+
{
44+
new Employee { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), Salary = 7700, IsActive = true },
45+
new Employee { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), Salary = 19000, IsActive = true },
46+
new Employee { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), Salary = 12000, IsActive = true },
47+
new Employee { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), Salary = 19000, IsActive = false },
48+
new Employee { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), Salary = 16500.50f, IsActive = true },
49+
new Employee { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 24000, IsActive = true },
50+
new Employee { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 21000, IsActive = true },
51+
new Employee { Id = 113, Name = "Merlin", Designation = "Senior Consultant", DOJ = new DateOnly(1989, 10, 2), Salary = 13500, IsActive = true },
52+
new Employee { Id = 117, Name = "Sharna", Designation = "Data Analyst", DOJ = new DateOnly(1994, 5, 12), Salary = 15800.10f, IsActive = true },
53+
new Employee { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), Salary = 14000, IsActive = true },
54+
new Employee { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), Salary = 8000, IsActive = true },
55+
new Employee { Id = 111, Name = "Glenda", Designation = "Data Engineer", DOJ = new DateOnly(1994, 1, 12), Salary = 17850, IsActive = true },
56+
};
57+
}
58+
59+
public record class Employee
60+
{
61+
public int Id { get; set; }
62+
public string? Name { get; set; }
63+
public string? Designation { get; set; }
64+
public DateOnly DOJ { get; set; }
65+
public float Salary { get; set; }
66+
public bool IsActive { get; set; }
67+
}
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<Grid TItem="Employee"
2+
Class="table table-hover table-bordered table-striped"
3+
DataProvider="EmployeesDataProvider"
4+
AllowSummary="true"
5+
Responsive="true">
6+
7+
<GridColumns>
8+
<GridColumn TItem="Employee" HeaderText="Id" PropertyName="Id">
9+
@context.Id
10+
</GridColumn>
11+
<GridColumn TItem="Employee" HeaderText="Employee Name" PropertyName="Name" SummaryType="GridSummaryColumnType.Count" SummaryValuePrefix="">
12+
@context.Name
13+
</GridColumn>
14+
<GridColumn TItem="Employee" HeaderText="Designation" PropertyName="Designation">
15+
@context.Designation
16+
</GridColumn>
17+
<GridColumn TItem="Employee" HeaderText="DOJ" PropertyName="DOJ">
18+
@context.DOJ
19+
</GridColumn>
20+
<GridColumn TItem="Employee" HeaderText="Salary" HeaderTextAlignment="Alignment.End" TextAlignment="Alignment.End" PropertyName="Salary" SummaryType="GridSummaryColumnType.Sum" SummaryValueDisplayFormat="C" SummaryValuePrefix="">
21+
@context.Salary.ToString("C")
22+
</GridColumn>
23+
<GridColumn TItem="Employee" HeaderText="Active" PropertyName="IsActive">
24+
@context.IsActive
25+
</GridColumn>
26+
</GridColumns>
27+
</Grid>
28+
29+
@code {
30+
private IEnumerable<Employee> employees = default!;
31+
32+
private async Task<GridDataProviderResult<Employee>> EmployeesDataProvider(GridDataProviderRequest<Employee> request)
33+
{
34+
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
35+
employees = GetEmployees(); // call a service or an API to pull the employees
36+
37+
return await Task.FromResult(request.ApplyTo(employees));
38+
}
39+
40+
private IEnumerable<Employee> GetEmployees()
41+
{
42+
return new List<Employee>
43+
{
44+
new Employee { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), Salary = 7700, IsActive = true },
45+
new Employee { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), Salary = 19000, IsActive = true },
46+
new Employee { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), Salary = 12000, IsActive = true },
47+
new Employee { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), Salary = 19000, IsActive = false },
48+
new Employee { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), Salary = 16500.50f, IsActive = true },
49+
new Employee { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 24000, IsActive = true },
50+
new Employee { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 21000, IsActive = true },
51+
new Employee { Id = 113, Name = "Merlin", Designation = "Senior Consultant", DOJ = new DateOnly(1989, 10, 2), Salary = 13500, IsActive = true },
52+
new Employee { Id = 117, Name = "Sharna", Designation = "Data Analyst", DOJ = new DateOnly(1994, 5, 12), Salary = 15800.10f, IsActive = true },
53+
new Employee { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), Salary = 14000, IsActive = true },
54+
new Employee { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), Salary = 8000, IsActive = true },
55+
new Employee { Id = 111, Name = "Glenda", Designation = "Data Engineer", DOJ = new DateOnly(1994, 1, 12), Salary = 17850, IsActive = true },
56+
};
57+
}
58+
59+
public record class Employee
60+
{
61+
public int Id { get; set; }
62+
public string? Name { get; set; }
63+
public string? Designation { get; set; }
64+
public DateOnly DOJ { get; set; }
65+
public float Salary { get; set; }
66+
public bool IsActive { get; set; }
67+
}
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<Grid TItem="Employee"
2+
Class="table table-hover table-bordered table-striped"
3+
DataProvider="EmployeesDataProvider"
4+
AllowSummary="true"
5+
Locale="en-IN"
6+
Responsive="true">
7+
8+
<GridColumns>
9+
<GridColumn TItem="Employee" HeaderText="Id" PropertyName="Id">
10+
@context.Id
11+
</GridColumn>
12+
<GridColumn TItem="Employee" HeaderText="Employee Name" PropertyName="Name" SummaryType="GridSummaryColumnType.Count">
13+
@context.Name
14+
</GridColumn>
15+
<GridColumn TItem="Employee" HeaderText="Designation" PropertyName="Designation">
16+
@context.Designation
17+
</GridColumn>
18+
<GridColumn TItem="Employee" HeaderText="DOJ" PropertyName="DOJ">
19+
@context.DOJ
20+
</GridColumn>
21+
<GridColumn TItem="Employee" HeaderText="Salary" HeaderTextAlignment="Alignment.End" TextAlignment="Alignment.End" PropertyName="Salary" SummaryType="GridSummaryColumnType.Sum" SummaryValueDisplayFormat="C">
22+
@context.Salary.ToString("C", System.Globalization.CultureInfo.GetCultureInfo("en-IN"))
23+
</GridColumn>
24+
<GridColumn TItem="Employee" HeaderText="Active" PropertyName="IsActive">
25+
@context.IsActive
26+
</GridColumn>
27+
</GridColumns>
28+
</Grid>
29+
30+
@code {
31+
private IEnumerable<Employee> employees = default!;
32+
33+
private async Task<GridDataProviderResult<Employee>> EmployeesDataProvider(GridDataProviderRequest<Employee> request)
34+
{
35+
if (employees is null) // pull employees only one time for client-side filtering, sorting, and paging
36+
employees = GetEmployees(); // call a service or an API to pull the employees
37+
38+
return await Task.FromResult(request.ApplyTo(employees));
39+
}
40+
41+
private IEnumerable<Employee> GetEmployees()
42+
{
43+
return new List<Employee>
44+
{
45+
new Employee { Id = 107, Name = "Alice", Designation = "AI Engineer", DOJ = new DateOnly(1998, 11, 17), Salary = 7700, IsActive = true },
46+
new Employee { Id = 103, Name = "Bob", Designation = "Senior DevOps Engineer", DOJ = new DateOnly(1985, 1, 5), Salary = 19000, IsActive = true },
47+
new Employee { Id = 106, Name = "John", Designation = "Data Engineer", DOJ = new DateOnly(1995, 4, 17), Salary = 12000, IsActive = true },
48+
new Employee { Id = 104, Name = "Pop", Designation = "Associate Architect", DOJ = new DateOnly(1985, 6, 8), Salary = 19000, IsActive = false },
49+
new Employee { Id = 105, Name = "Ronald", Designation = "Senior Data Engineer", DOJ = new DateOnly(1991, 8, 23), Salary = 16500.50f, IsActive = true },
50+
new Employee { Id = 102, Name = "Line", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 24000, IsActive = true },
51+
new Employee { Id = 101, Name = "Daniel", Designation = "Architect", DOJ = new DateOnly(1977, 1, 12), Salary = 21000, IsActive = true },
52+
new Employee { Id = 113, Name = "Merlin", Designation = "Senior Consultant", DOJ = new DateOnly(1989, 10, 2), Salary = 13500, IsActive = true },
53+
new Employee { Id = 117, Name = "Sharna", Designation = "Data Analyst", DOJ = new DateOnly(1994, 5, 12), Salary = 15800.10f, IsActive = true },
54+
new Employee { Id = 108, Name = "Zayne", Designation = "Data Analyst", DOJ = new DateOnly(1991, 1, 1), Salary = 14000, IsActive = true },
55+
new Employee { Id = 109, Name = "Isha", Designation = "App Maker", DOJ = new DateOnly(1996, 7, 1), Salary = 8000, IsActive = true },
56+
new Employee { Id = 111, Name = "Glenda", Designation = "Data Engineer", DOJ = new DateOnly(1994, 1, 12), Salary = 17850, IsActive = true },
57+
};
58+
}
59+
60+
public record class Employee
61+
{
62+
public int Id { get; set; }
63+
public string? Name { get; set; }
64+
public string? Designation { get; set; }
65+
public DateOnly DOJ { get; set; }
66+
public float Salary { get; set; }
67+
public bool IsActive { get; set; }
68+
}
69+
}

BlazorBootstrap.Demo.RCL/Components/Pages/Grid/16-summary/Grid_Summary_Documentation.razor

+24-3
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,33 @@
2626
</Section>
2727

2828
<Section Size="HeadingSize.H2" Name="Summary with Filters and Paging" PageUrl="@pageUrl" Link="summary-with-filters-paging">
29-
<Callout Color="CalloutColor.Danger">
30-
<b>NOTE: </b>Summaries will be calculated based on the current page data.
31-
</Callout>
29+
<div class="mb-3">
30+
Summaries will be calculated based on the current page data.
31+
</div>
3232
<Demo Type="typeof(Grid_Demo_02_Summary_with_Filters_Paging)" Tabs="true" />
3333
</Section>
3434

35+
<Section Size="HeadingSize.H2" Name="Change prefix" PageUrl="@pageUrl" Link="change-prefix">
36+
<div class="mb-3">
37+
Set the <code>SummaryValuePrefix</code> parameter to custom string to change the prefix from the summary value.
38+
</div>
39+
<Demo Type="typeof(Grid_Demo_03_Change_Prefix)" Tabs="true" />
40+
</Section>
41+
42+
<Section Size="HeadingSize.H2" Name="Remove prefix" PageUrl="@pageUrl" Link="remove-prefix">
43+
<div class="mb-3">
44+
Set the <code>SummaryValuePrefix</code> parameter to empty string to remove the prefix from the summary value.
45+
</div>
46+
<Demo Type="typeof(Grid_Demo_04_Remove_Prefix)" Tabs="true" />
47+
</Section>
48+
49+
<Section Size="HeadingSize.H2" Name="Locale" PageUrl="@pageUrl" Link="locale">
50+
<div class="mb-3">
51+
Set the <code>Locale</code> parameter on the Grid to change the <code>CultureInfo</code> of the summary.
52+
</div>
53+
<Demo Type="typeof(Grid_Demo_05_Locale)" Tabs="true" />
54+
</Section>
55+
3556
@code {
3657
private const string pageUrl = RouteConstants.Demos_Grid_Summary_Documentation;
3758
private const string pageTitle = "Blazor Grid - Summary";

blazorbootstrap/Components/Grid/Grid.razor

+1-1
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@
212212
}
213213
else if (column.SummaryType != GridSummaryColumnType.None)
214214
{
215-
<td>@GetColumnSummaryValue(column.SummaryType, column.PropertyName, column.SummaryValueDisplayFormat)</td>
215+
<td class="@column.TextAlignment.ToTextAlignmentClass()">@GetColumnSummaryValue(column.SummaryType, column.PropertyName, column.SummaryValueDisplayFormat, column.SummaryValuePrefix)</td>
216216
}
217217
}
218218
}

blazorbootstrap/Components/Grid/Grid.razor.cs

+32-9
Original file line numberDiff line numberDiff line change
@@ -123,41 +123,40 @@ protected override Task OnParametersSetAsync()
123123
.Where(column => column.Filterable && column.GetFilterOperator() != FilterOperator.None && !string.IsNullOrWhiteSpace(column.GetFilterValue()))
124124
?.Select(column => new FilterItem(column.PropertyName, column.GetFilterValue(), column.GetFilterOperator(), column.StringComparison));
125125

126-
private string GetColumnSummaryValue(GridSummaryColumnType type, string propertyName, string format)
126+
private string GetColumnSummaryValue(GridSummaryColumnType type, string propertyName, string format, string prefix)
127127
{
128-
string? prefix = null;
129128
double value = 0;
130129

131130
if (type == GridSummaryColumnType.Average)
132131
{
133-
prefix = "Avg";
132+
prefix ??= "Avg: ";
134133
value = items?.Average(x => Convert.ToDouble(x.GetType().GetProperty(propertyName)?.GetValue(x))) ?? 0;
135134
}
136135
else if (type == GridSummaryColumnType.Count)
137136
{
138-
prefix = "Count";
137+
prefix ??= "Count: ";
139138
value = items?.Where(x => x.GetType().GetProperty(propertyName)?.GetValue(x) is not null).Count() ?? 0;
140139
}
141140
else if (type == GridSummaryColumnType.Max)
142141
{
143-
prefix = "Max";
142+
prefix ??= "Max: ";
144143
value = items?.Max(x => Convert.ToDouble(x.GetType().GetProperty(propertyName)?.GetValue(x))) ?? 0;
145144
}
146145
else if (type == GridSummaryColumnType.Min)
147146
{
148-
prefix = "Min";
147+
prefix ??= "Min: ";
149148
value = items?.Min(x => Convert.ToDouble(x.GetType().GetProperty(propertyName)?.GetValue(x))) ?? 0;
150149
}
151150
else if (type == GridSummaryColumnType.Sum)
152151
{
153-
prefix = "Total";
152+
prefix ??= "Total: ";
154153
value = items?.Sum(x => Convert.ToDouble(x.GetType().GetProperty(propertyName)?.GetValue(x))) ?? 0;
155154
}
156155

157156
if (string.IsNullOrWhiteSpace(format))
158-
return $"{prefix}: {value}";
157+
return $"{prefix}{value}";
159158
else
160-
return $"{prefix}: {value.ToString(format)}";
159+
return $"{prefix}{value.ToString(format, GetCultureInfo())}";
161160
}
162161

163162
/// <summary>
@@ -353,6 +352,21 @@ private RenderFragment ChildSelectionTemplate(int rowIndex, TItem rowData) =>
353352
builder.CloseElement(); // close: th
354353
};
355354

355+
private CultureInfo GetCultureInfo()
356+
{
357+
if (string.IsNullOrWhiteSpace(Locale))
358+
return CultureInfo.InvariantCulture;
359+
360+
try
361+
{
362+
return CultureInfo.GetCultureInfo(Locale);
363+
}
364+
catch (CultureNotFoundException)
365+
{
366+
return CultureInfo.InvariantCulture;
367+
}
368+
}
369+
356370
private IEnumerable<SortingItem<TItem>>? GetDefaultSorting() =>
357371
!AllowSorting || columns == null || !columns.Any()
358372
? null
@@ -893,6 +907,15 @@ private void SetFilters(IEnumerable<FilterItem> filterItems)
893907
//[EditorRequired]
894908
public string ItemsPerPageText { get; set; } = "Items per page"!;
895909

910+
/// <summary>
911+
/// Gets or sets the locale.
912+
/// <para>
913+
/// Default value is 'en-US'.
914+
/// </para>
915+
/// </summary>
916+
[Parameter]
917+
public string? Locale { get; set; } = "en-US";
918+
896919
/// <summary>
897920
/// This event is triggered when the user clicks on the row.
898921
/// Set AllowRowClick to true to enable row clicking.

blazorbootstrap/Components/Grid/GridColumn.razor.cs

+11
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,17 @@ private async Task OnSortClickAsync()
512512
[Parameter]
513513
public string? SummaryValueDisplayFormat { get; set; }
514514

515+
/// <summary>
516+
/// Gets or sets the summary value prefix. If set, it will be displayed before the summary value.
517+
/// Otherwise, based on the <see cref="SummaryType"/>, default prefix will be displayed.
518+
/// To remove the default prefix, set this property to an empty string.
519+
/// <para>
520+
/// Example: "Total: ", "Average: ", etc.
521+
/// </para>
522+
/// </summary>
523+
[Parameter]
524+
public string? SummaryValuePrefix { get; set; }
525+
515526
/// <summary>
516527
/// Gets or sets the text alignment.
517528
/// </summary>

0 commit comments

Comments
 (0)