From 5408647ea551b2a3d83aa447af2168cbb093b7f8 Mon Sep 17 00:00:00 2001 From: "Knotek, Josef" Date: Tue, 9 Jan 2024 12:54:06 +0100 Subject: [PATCH 1/7] Parameter - Selected NamedView --- BlazorAppTest/Pages/HxNamedViewListTest.razor | 115 ++++++++++++++++++ .../NamedViews/HxNamedViewList.razor | 18 ++- .../NamedViews/HxNamedViewList.razor.cs | 1 + 3 files changed, 128 insertions(+), 6 deletions(-) create mode 100644 BlazorAppTest/Pages/HxNamedViewListTest.razor diff --git a/BlazorAppTest/Pages/HxNamedViewListTest.razor b/BlazorAppTest/Pages/HxNamedViewListTest.razor new file mode 100644 index 00000000..7e0b2f12 --- /dev/null +++ b/BlazorAppTest/Pages/HxNamedViewListTest.razor @@ -0,0 +1,115 @@ +@page "/HxNamedViewListTest" +@using System.Globalization + +

HxNameViewList

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Edit: @currentItem?.LCID + + + +@code { + [Inject] protected NavigationManager NavigationManager { get; set; } + + private EditableCultureInfo currentItem; + private FilterModelDto filterModel = new FilterModelDto(); + private HxGrid gridComponent; + + private NamedView selectedNamedView; + + private readonly IEnumerable> namedViews = new List>() + { + new NamedView("Minimum = 1", () => new FilterModelDto { MinimumLCID = 1 } ), + new NamedView("Minimum = 50", () => new FilterModelDto { MinimumLCID = 50 }), + new NamedView("Minimum = 100", () => new FilterModelDto { MinimumLCID = 100 }) + }; + + private List localEditableCultureInfos = CultureInfo.GetCultures(CultureTypes.AllCultures).Select(c => new EditableCultureInfo() + { + LCID = c.LCID, + DisplayName = c.DisplayName, + Name = c.Name, + EnglishName = c.EnglishName + }).ToList(); + + private Task> LoadDataItems(GridDataProviderRequest request) + { + IEnumerable result = localEditableCultureInfos.Where(i => i.LCID >= filterModel.MinimumLCID).ToList(); + + return Task.FromResult(request.ApplyTo(result)); + } + + private async Task HandleFilterModelChanged(FilterModelDto newFilterModel) + { + filterModel = newFilterModel; + await gridComponent.RefreshDataAsync(); + } + + protected async Task NamedViewSelected(NamedView namedView) + { + filterModel = namedView.Filter(); + selectedNamedView = namedView; + await gridComponent.RefreshDataAsync(); + } + + private async Task DeleteItemClicked(EditableCultureInfo editableCultureInfo) + { + localEditableCultureInfos.Remove(editableCultureInfo); + await gridComponent.RefreshDataAsync(); + } + + private Task HandleSelectedDataItemChanged(EditableCultureInfo selection) + { + currentItem = selection; + // await dataItemEditComponent.ShowAsync(); + return Task.CompletedTask; + } + + private Task NewItemClicked() + { + currentItem = new(); + // await dataItemEditComponent.ShowAsync(); + return Task.CompletedTask; + } + + public record FilterModelDto + { + public int MinimumLCID { get; set; } + } + + private record EditableCultureInfo + { + public int LCID { get; set; } + public string DisplayName { get; set; } + public string Name { get; set; } + public string EnglishName { get; set; } + } +} \ No newline at end of file diff --git a/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor b/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor index e643cc10..bacaab33 100644 --- a/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor +++ b/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor @@ -3,10 +3,16 @@ @if ((NamedViews != null) && NamedViews.Any()) { - + } \ No newline at end of file diff --git a/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor.cs b/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor.cs index 783ceae0..37cde5a5 100644 --- a/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor.cs +++ b/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor.cs @@ -8,6 +8,7 @@ public partial class HxNamedViewList { [Parameter] public IEnumerable> NamedViews { get; set; } + [Parameter] public NamedView SelectedNamedView { get; set; } [Parameter] public TFilterModel FilterModel { get; set; } From 4a0140c3631e61c372e542ca765d99c163149b35 Mon Sep 17 00:00:00 2001 From: "Knotek, Josef" Date: Tue, 9 Jan 2024 13:02:40 +0100 Subject: [PATCH 2/7] Demos changed to different url. --- .../NamedViews/HxNamedViewList.razor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor.cs b/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor.cs index 37cde5a5..a4ea5532 100644 --- a/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor.cs +++ b/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor.cs @@ -2,7 +2,7 @@ /// /// List of named-views for .
-/// Full documentation and demos: https://havit.blazor.eu/components/HxNamedViewList +/// Full documentation and demos: https://havit.blazor.eu/components/HxListLayout#named-views ///
public partial class HxNamedViewList From b4c5f7e9b3eb47a93fc83b9176b1fa258fb084c2 Mon Sep 17 00:00:00 2001 From: "Knotek, Josef" Date: Tue, 9 Jan 2024 13:31:01 +0100 Subject: [PATCH 3/7] Modified demo. --- BlazorAppTest/Pages/HxNamedViewListTest.razor | 1 + .../HxListLayoutDoc/HxListLayout_Demo_Basic.razor | 15 +++++++++++++++ .../Havit.Blazor.Components.Web.Bootstrap.xml | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/BlazorAppTest/Pages/HxNamedViewListTest.razor b/BlazorAppTest/Pages/HxNamedViewListTest.razor index 7e0b2f12..9ba04625 100644 --- a/BlazorAppTest/Pages/HxNamedViewListTest.razor +++ b/BlazorAppTest/Pages/HxNamedViewListTest.razor @@ -70,6 +70,7 @@ private async Task HandleFilterModelChanged(FilterModelDto newFilterModel) { filterModel = newFilterModel; + this.selectedNamedView = namedViews.Where(n => n.Filter.Invoke().MinimumLCID == newFilterModel.MinimumLCID).FirstOrDefault(); await gridComponent.RefreshDataAsync(); } diff --git a/Havit.Blazor.Documentation/Pages/Components/HxListLayoutDoc/HxListLayout_Demo_Basic.razor b/Havit.Blazor.Documentation/Pages/Components/HxListLayoutDoc/HxListLayout_Demo_Basic.razor index 0186d8ee..fd840a2c 100644 --- a/Havit.Blazor.Documentation/Pages/Components/HxListLayoutDoc/HxListLayout_Demo_Basic.razor +++ b/Havit.Blazor.Documentation/Pages/Components/HxListLayoutDoc/HxListLayout_Demo_Basic.razor @@ -33,6 +33,7 @@ private EditableCultureInfo currentItem; private HxGrid gridComponent; + private NamedView selectedNamedView; private List localEditableCultureInfos = CultureInfo.GetCultures(CultureTypes.AllCultures).Select(c => new EditableCultureInfo() { @@ -49,6 +50,20 @@ return Task.FromResult(request.ApplyTo(result)); } + private async Task HandleFilterModelChanged(FilterModelDto newFilterModel) + { + filterModel = newFilterModel; + this.selectedNamedView = namedViews.Where(n => n.Filter.Invoke().MinimumLCID == newFilterModel.MinimumLCID).FirstOrDefault(); + await gridComponent.RefreshDataAsync(); + } + + protected async Task NamedViewSelected(NamedView namedView) + { + filterModel = namedView.Filter(); + this.selectedNamedView = namedView; + await gridComponent.RefreshDataAsync(); + } + private async Task DeleteItemClicked(EditableCultureInfo editableCultureInfo) { localEditableCultureInfos.Remove(editableCultureInfo); diff --git a/Havit.Blazor.Documentation/XmlDoc/Havit.Blazor.Components.Web.Bootstrap.xml b/Havit.Blazor.Documentation/XmlDoc/Havit.Blazor.Components.Web.Bootstrap.xml index 3ced733e..65cd7b0b 100644 --- a/Havit.Blazor.Documentation/XmlDoc/Havit.Blazor.Components.Web.Bootstrap.xml +++ b/Havit.Blazor.Documentation/XmlDoc/Havit.Blazor.Components.Web.Bootstrap.xml @@ -7722,7 +7722,7 @@ List of named views for .
- Full documentation and demos: https://havit.blazor.eu/components/HxNamedViewList + Full documentation and demos: https://havit.blazor.eu/components/HxListLayout#named-views
From a316e15da3e20535be0793b02a87e375ae116baa Mon Sep 17 00:00:00 2001 From: "Knotek, Josef" Date: Tue, 9 Jan 2024 13:45:28 +0100 Subject: [PATCH 4/7] Demo fix. --- .../HxListLayout_Demo_Basic.razor | 15 ------- .../HxListLayout_Demo_NamedViews.razor | 43 ++++++++++--------- .../Havit.Blazor.Components.Web.Bootstrap.xml | 2 +- 3 files changed, 24 insertions(+), 36 deletions(-) diff --git a/Havit.Blazor.Documentation/Pages/Components/HxListLayoutDoc/HxListLayout_Demo_Basic.razor b/Havit.Blazor.Documentation/Pages/Components/HxListLayoutDoc/HxListLayout_Demo_Basic.razor index fd840a2c..0186d8ee 100644 --- a/Havit.Blazor.Documentation/Pages/Components/HxListLayoutDoc/HxListLayout_Demo_Basic.razor +++ b/Havit.Blazor.Documentation/Pages/Components/HxListLayoutDoc/HxListLayout_Demo_Basic.razor @@ -33,7 +33,6 @@ private EditableCultureInfo currentItem; private HxGrid gridComponent; - private NamedView selectedNamedView; private List localEditableCultureInfos = CultureInfo.GetCultures(CultureTypes.AllCultures).Select(c => new EditableCultureInfo() { @@ -50,20 +49,6 @@ return Task.FromResult(request.ApplyTo(result)); } - private async Task HandleFilterModelChanged(FilterModelDto newFilterModel) - { - filterModel = newFilterModel; - this.selectedNamedView = namedViews.Where(n => n.Filter.Invoke().MinimumLCID == newFilterModel.MinimumLCID).FirstOrDefault(); - await gridComponent.RefreshDataAsync(); - } - - protected async Task NamedViewSelected(NamedView namedView) - { - filterModel = namedView.Filter(); - this.selectedNamedView = namedView; - await gridComponent.RefreshDataAsync(); - } - private async Task DeleteItemClicked(EditableCultureInfo editableCultureInfo) { localEditableCultureInfos.Remove(editableCultureInfo); diff --git a/Havit.Blazor.Documentation/Pages/Components/HxListLayoutDoc/HxListLayout_Demo_NamedViews.razor b/Havit.Blazor.Documentation/Pages/Components/HxListLayoutDoc/HxListLayout_Demo_NamedViews.razor index 8b0afadd..aec7dcea 100644 --- a/Havit.Blazor.Documentation/Pages/Components/HxListLayoutDoc/HxListLayout_Demo_NamedViews.razor +++ b/Havit.Blazor.Documentation/Pages/Components/HxListLayoutDoc/HxListLayout_Demo_NamedViews.razor @@ -4,7 +4,8 @@ @bind-FilterModel="filterModel" @bind-FilterModel:after="RefreshDataAsync" NamedViews="namedViews" - OnNamedViewSelected="NamedViewSelected" /> + OnNamedViewSelected="NamedViewSelected" + SelectedNamedView="selectedNamedView" /> @@ -42,20 +43,21 @@ @code { - [Inject] protected NavigationManager NavigationManager { get; set; } + [Inject] protected NavigationManager NavigationManager { get; set; } - private EditableCultureInfo currentItem; - private FilterModelDto filterModel = new FilterModelDto(); - private HxGrid gridComponent; + private EditableCultureInfo currentItem; + private FilterModelDto filterModel = new FilterModelDto(); + private HxGrid gridComponent; + private NamedView selectedNamedView; - private readonly IEnumerable> namedViews = new List>() + private readonly IEnumerable> namedViews = new List>() { new NamedView("Minimum = 1", () => new FilterModelDto { MinimumLCID = 1 } ), new NamedView("Minimum = 50", () => new FilterModelDto { MinimumLCID = 50 }), new NamedView("Minimum = 100", () => new FilterModelDto { MinimumLCID = 100 }) }; - private List localEditableCultureInfos = CultureInfo.GetCultures(CultureTypes.AllCultures).Select(c => new EditableCultureInfo() + private List localEditableCultureInfos = CultureInfo.GetCultures(CultureTypes.AllCultures).Select(c => new EditableCultureInfo() { LCID = c.LCID, DisplayName = c.DisplayName, @@ -63,22 +65,23 @@ EnglishName = c.EnglishName }).ToList(); - private Task> LoadDataItems(GridDataProviderRequest request) - { - IEnumerable result = localEditableCultureInfos.Where(i => i.LCID >= filterModel.MinimumLCID).ToList(); + private Task> LoadDataItems(GridDataProviderRequest request) + { + IEnumerable result = localEditableCultureInfos.Where(i => i.LCID >= filterModel.MinimumLCID).ToList(); - return Task.FromResult(request.ApplyTo(result)); - } + return Task.FromResult(request.ApplyTo(result)); + } - private async Task RefreshDataAsync() - { - await gridComponent.RefreshDataAsync(); - } + private async Task RefreshDataAsync() + { + await gridComponent.RefreshDataAsync(); + } - protected async Task NamedViewSelected(NamedView namedView) - { - filterModel = namedView.Filter(); - await gridComponent.RefreshDataAsync(); + protected async Task NamedViewSelected(NamedView namedView) + { + filterModel = namedView.Filter(); + selectedNamedView = namedView; + await gridComponent.RefreshDataAsync(); } private async Task DeleteItemClicked(EditableCultureInfo editableCultureInfo) diff --git a/Havit.Blazor.Documentation/XmlDoc/Havit.Blazor.Components.Web.Bootstrap.xml b/Havit.Blazor.Documentation/XmlDoc/Havit.Blazor.Components.Web.Bootstrap.xml index 65cd7b0b..f01feba1 100644 --- a/Havit.Blazor.Documentation/XmlDoc/Havit.Blazor.Components.Web.Bootstrap.xml +++ b/Havit.Blazor.Documentation/XmlDoc/Havit.Blazor.Components.Web.Bootstrap.xml @@ -7721,7 +7721,7 @@ - List of named views for .
+ List of named-views for .
Full documentation and demos: https://havit.blazor.eu/components/HxListLayout#named-views
From f24ddc1f6ec67dd8e92122a709cc168c9dc835fc Mon Sep 17 00:00:00 2001 From: "Knotek, Josef" Date: Tue, 9 Jan 2024 14:17:23 +0100 Subject: [PATCH 5/7] Fix of the second filter on demo page. --- .../HxListLayoutDoc/HxListLayout_Demo_NamedViews.razor | 1 + 1 file changed, 1 insertion(+) diff --git a/Havit.Blazor.Documentation/Pages/Components/HxListLayoutDoc/HxListLayout_Demo_NamedViews.razor b/Havit.Blazor.Documentation/Pages/Components/HxListLayoutDoc/HxListLayout_Demo_NamedViews.razor index aec7dcea..b249429a 100644 --- a/Havit.Blazor.Documentation/Pages/Components/HxListLayoutDoc/HxListLayout_Demo_NamedViews.razor +++ b/Havit.Blazor.Documentation/Pages/Components/HxListLayoutDoc/HxListLayout_Demo_NamedViews.razor @@ -74,6 +74,7 @@ private async Task RefreshDataAsync() { + selectedNamedView = namedViews.Where(n => n.Filter.Invoke().MinimumLCID == filterModel.MinimumLCID).FirstOrDefault(); await gridComponent.RefreshDataAsync(); } From e26244779e406e4b9bb1ccac9a4dc0617053501e Mon Sep 17 00:00:00 2001 From: Robert Haken Date: Fri, 12 Jan 2024 10:11:29 +0100 Subject: [PATCH 6/7] HxListLayout - HxNamedViewList consolidation --- BlazorAppTest/Pages/HxListLayoutTest.razor | 6 +- BlazorAppTest/Pages/HxListLayoutTest.razor.cs | 11 +- BlazorAppTest/Pages/HxNamedViewListTest.razor | 116 ------------------ .../NamedViews/HxNamedViewList.razor | 34 ++--- .../NamedViews/HxNamedViewList.razor.cs | 50 +++++--- .../HxListLayout_Demo_NamedViews.razor | 16 +-- .../Havit.Blazor.Components.Web.Bootstrap.xml | 26 +++- 7 files changed, 86 insertions(+), 173 deletions(-) delete mode 100644 BlazorAppTest/Pages/HxNamedViewListTest.razor diff --git a/BlazorAppTest/Pages/HxListLayoutTest.razor b/BlazorAppTest/Pages/HxListLayoutTest.razor index 0a9b11ed..6b7b3565 100644 --- a/BlazorAppTest/Pages/HxListLayoutTest.razor +++ b/BlazorAppTest/Pages/HxListLayoutTest.razor @@ -2,9 +2,9 @@

HxListLayout

- + - + @@ -26,7 +26,7 @@ - + diff --git a/BlazorAppTest/Pages/HxListLayoutTest.razor.cs b/BlazorAppTest/Pages/HxListLayoutTest.razor.cs index 33893051..cef62e56 100644 --- a/BlazorAppTest/Pages/HxListLayoutTest.razor.cs +++ b/BlazorAppTest/Pages/HxListLayoutTest.razor.cs @@ -9,13 +9,14 @@ public partial class HxListLayoutTest private DataItemDto currentItem; private FilterModelDto filterModel = new FilterModelDto(); + private NamedView selectedNamedView; private HxGrid gridComponent; private readonly IEnumerable> namedViews = new List>() { - new NamedView("Minimum = 1", () => new FilterModelDto { MinimumItemId = 1 }), - new NamedView("Minimum = 2", () => new FilterModelDto { MinimumItemId = 2 }), - new NamedView("Minimum = 3", () => new FilterModelDto { MinimumItemId = 3 }) + new NamedView("Minimum ID = 1", () => new FilterModelDto { MinimumItemId = 1 }), + new NamedView("Minimum ID = 2", () => new FilterModelDto { MinimumItemId = 2 }), + new NamedView("Minimum ID = 3", () => new FilterModelDto { MinimumItemId = 3 }) }; private Task> LoadDataItems(GridDataProviderRequest request) @@ -54,9 +55,9 @@ private async Task HandleFilterModelChanged(FilterModelDto newFilterModel) await gridComponent.RefreshDataAsync(); } - protected async Task NamedViewSelected(NamedView namedView) + protected async Task HandleSelectedNamedViewChanged() { - filterModel = namedView.Filter(); + filterModel = selectedNamedView.Filter(); await gridComponent.RefreshDataAsync(); } diff --git a/BlazorAppTest/Pages/HxNamedViewListTest.razor b/BlazorAppTest/Pages/HxNamedViewListTest.razor deleted file mode 100644 index 9ba04625..00000000 --- a/BlazorAppTest/Pages/HxNamedViewListTest.razor +++ /dev/null @@ -1,116 +0,0 @@ -@page "/HxNamedViewListTest" -@using System.Globalization - -

HxNameViewList

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Edit: @currentItem?.LCID - - - -@code { - [Inject] protected NavigationManager NavigationManager { get; set; } - - private EditableCultureInfo currentItem; - private FilterModelDto filterModel = new FilterModelDto(); - private HxGrid gridComponent; - - private NamedView selectedNamedView; - - private readonly IEnumerable> namedViews = new List>() - { - new NamedView("Minimum = 1", () => new FilterModelDto { MinimumLCID = 1 } ), - new NamedView("Minimum = 50", () => new FilterModelDto { MinimumLCID = 50 }), - new NamedView("Minimum = 100", () => new FilterModelDto { MinimumLCID = 100 }) - }; - - private List localEditableCultureInfos = CultureInfo.GetCultures(CultureTypes.AllCultures).Select(c => new EditableCultureInfo() - { - LCID = c.LCID, - DisplayName = c.DisplayName, - Name = c.Name, - EnglishName = c.EnglishName - }).ToList(); - - private Task> LoadDataItems(GridDataProviderRequest request) - { - IEnumerable result = localEditableCultureInfos.Where(i => i.LCID >= filterModel.MinimumLCID).ToList(); - - return Task.FromResult(request.ApplyTo(result)); - } - - private async Task HandleFilterModelChanged(FilterModelDto newFilterModel) - { - filterModel = newFilterModel; - this.selectedNamedView = namedViews.Where(n => n.Filter.Invoke().MinimumLCID == newFilterModel.MinimumLCID).FirstOrDefault(); - await gridComponent.RefreshDataAsync(); - } - - protected async Task NamedViewSelected(NamedView namedView) - { - filterModel = namedView.Filter(); - selectedNamedView = namedView; - await gridComponent.RefreshDataAsync(); - } - - private async Task DeleteItemClicked(EditableCultureInfo editableCultureInfo) - { - localEditableCultureInfos.Remove(editableCultureInfo); - await gridComponent.RefreshDataAsync(); - } - - private Task HandleSelectedDataItemChanged(EditableCultureInfo selection) - { - currentItem = selection; - // await dataItemEditComponent.ShowAsync(); - return Task.CompletedTask; - } - - private Task NewItemClicked() - { - currentItem = new(); - // await dataItemEditComponent.ShowAsync(); - return Task.CompletedTask; - } - - public record FilterModelDto - { - public int MinimumLCID { get; set; } - } - - private record EditableCultureInfo - { - public int LCID { get; set; } - public string DisplayName { get; set; } - public string Name { get; set; } - public string EnglishName { get; set; } - } -} \ No newline at end of file diff --git a/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor b/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor index bacaab33..2cec3fac 100644 --- a/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor +++ b/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor @@ -1,18 +1,24 @@ @namespace Havit.Blazor.Components.Web.Bootstrap -@typeparam TFilterModel +@typeparam TItem -@if ((NamedViews != null) && NamedViews.Any()) +@if ((Items != null) && Items.Any()) { - + } \ No newline at end of file diff --git a/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor.cs b/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor.cs index 6cd16c9c..1570ab1f 100644 --- a/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor.cs +++ b/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor.cs @@ -4,35 +4,49 @@ /// List of named-views for .
/// Full documentation and demos: https://havit.blazor.eu/components/HxListLayout#named-views /// - -public partial class HxNamedViewList +public partial class HxNamedViewList { - [Parameter] public IEnumerable> NamedViews { get; set; } - [Parameter] public NamedView SelectedNamedView { get; set; } + /// + /// The items to display. + /// + [Parameter, EditorRequired] public IEnumerable Items { get; set; } - [Parameter] public TFilterModel FilterModel { get; set; } + /// + /// Selected item (highlighted in the list with .active CSS class). + /// + [Parameter] public TItem SelectedItem { get; set; } + [Parameter] public EventCallback SelectedItemChanged { get; set; } + /// + /// Triggers the event. Allows interception of the event in derived components. + /// + protected virtual Task InvokeSelectedItemChangedAsync(TItem itemSelected) => SelectedItemChanged.InvokeAsync(itemSelected); - [Parameter] public EventCallback FilterModelChanged { get; set; } /// - /// Triggers the event. Allows interception of the event in derived components. + /// Selects the text to display from the item. + /// You must set either this parameter or . + /// There is a special case when TItem is - in that case, the is used as the default text selector. /// - protected virtual Task InvokeFilterModelChangedAsync(TFilterModel newFilterModel) => FilterModelChanged.InvokeAsync(newFilterModel); + [Parameter] public Func TextSelector { get; set; } - [Parameter] public EventCallback> OnNamedViewSelected { get; set; } /// - /// Triggers the event. Allows interception of the event in derived components. + /// The template that defines how items in the component are displayed (optional). + /// You must set either this parameter or . /// - protected virtual Task InvokeOnNamedViewSelectedAsync(NamedView namedViewSelected) => OnNamedViewSelected.InvokeAsync(namedViewSelected); + [Parameter] public RenderFragment ItemTemplate { get; set; } - protected async Task HandleNamedViewClick(NamedView namedView) + protected override void OnParametersSet() { - TFilterModel newFilter = namedView.Filter(); - if (newFilter != null) + if ((TextSelector == null) && (ItemTemplate == null)) { - FilterModel = newFilter; // BEWARE, the filter has to be cloned - await InvokeFilterModelChangedAsync(newFilter); + // special case for NamedView + if (typeof(TItem).IsGenericType && (typeof(TItem).GetGenericTypeDefinition() == typeof(NamedView<>))) + { + TextSelector = item => (string)typeof(TItem).GetProperty(nameof(NamedView.Name)).GetValue(item); + } + else + { + throw new InvalidOperationException($"Either {nameof(TextSelector)} or {nameof(ItemTemplate)} must be set."); + } } - - await InvokeOnNamedViewSelectedAsync(namedView); } } diff --git a/Havit.Blazor.Documentation/Pages/Components/HxListLayoutDoc/HxListLayout_Demo_NamedViews.razor b/Havit.Blazor.Documentation/Pages/Components/HxListLayoutDoc/HxListLayout_Demo_NamedViews.razor index b249429a..9e7d6733 100644 --- a/Havit.Blazor.Documentation/Pages/Components/HxListLayoutDoc/HxListLayout_Demo_NamedViews.razor +++ b/Havit.Blazor.Documentation/Pages/Components/HxListLayoutDoc/HxListLayout_Demo_NamedViews.razor @@ -1,15 +1,7 @@  - + - - - @@ -74,14 +66,12 @@ private async Task RefreshDataAsync() { - selectedNamedView = namedViews.Where(n => n.Filter.Invoke().MinimumLCID == filterModel.MinimumLCID).FirstOrDefault(); await gridComponent.RefreshDataAsync(); } - protected async Task NamedViewSelected(NamedView namedView) + protected async Task HandleSelectedNamedViewChanged() { - filterModel = namedView.Filter(); - selectedNamedView = namedView; + filterModel = selectedNamedView.Filter(); await gridComponent.RefreshDataAsync(); } diff --git a/Havit.Blazor.Documentation/XmlDoc/Havit.Blazor.Components.Web.Bootstrap.xml b/Havit.Blazor.Documentation/XmlDoc/Havit.Blazor.Components.Web.Bootstrap.xml index f01feba1..7bc729ff 100644 --- a/Havit.Blazor.Documentation/XmlDoc/Havit.Blazor.Components.Web.Bootstrap.xml +++ b/Havit.Blazor.Documentation/XmlDoc/Havit.Blazor.Components.Web.Bootstrap.xml @@ -7725,14 +7725,32 @@ Full documentation and demos: https://havit.blazor.eu/components/HxListLayout#named-views - + - Triggers the event. Allows interception of the event in derived components. + The items to display. - + - Triggers the event. Allows interception of the event in derived components. + Selected item (highlighted in the list with .active CSS class). + + + + + Triggers the event. Allows interception of the event in derived components. + + + + + Selects the text to display from the item. + You must set either this parameter or . + There is a special case when TItem is - in that case, the is used as the default text selector. + + + + + The template that defines how items in the component are displayed (optional). + You must set either this parameter or . From e6ff9fa06368ebaaaf427686cfc82b7473e2e16e Mon Sep 17 00:00:00 2001 From: Robert Haken Date: Fri, 12 Jan 2024 15:15:02 +0100 Subject: [PATCH 7/7] HxListLayout - Named Views complete overhaul (HxNamedViewList component removed) BREAKING CHANGE --- BlazorAppTest/Pages/HxListLayoutTest.razor | 36 ++++---- BlazorAppTest/Pages/HxListLayoutTest.razor.cs | 10 +-- .../Layouts/HxListLayout.razor | 83 +++++++++++-------- .../Layouts/HxListLayout.razor.cs | 55 +++++++++++- .../NamedViews/HxNamedViewList.razor | 24 ------ .../NamedViews/HxNamedViewList.razor.cs | 52 ------------ .../NamedViews/NamedView.cs | 30 ++++--- .../HxListLayout_Demo_NamedViews.razor | 73 +++++++++------- .../HxNamedViewList_Documentation.razor | 6 -- .../Shared/Sidebar.razor | 1 - .../Havit.Blazor.Components.Web.Bootstrap.xml | 78 ++++++++++++----- 11 files changed, 236 insertions(+), 212 deletions(-) delete mode 100644 Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor delete mode 100644 Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor.cs delete mode 100644 Havit.Blazor.Documentation/Pages/Components/HxNamedViewListDoc/HxNamedViewList_Documentation.razor diff --git a/BlazorAppTest/Pages/HxListLayoutTest.razor b/BlazorAppTest/Pages/HxListLayoutTest.razor index 6b7b3565..def32f46 100644 --- a/BlazorAppTest/Pages/HxListLayoutTest.razor +++ b/BlazorAppTest/Pages/HxListLayoutTest.razor @@ -2,34 +2,34 @@

HxListLayout

- - - - - - - - - - - + + + + + + + + - - - - - - + + + + + + - + diff --git a/BlazorAppTest/Pages/HxListLayoutTest.razor.cs b/BlazorAppTest/Pages/HxListLayoutTest.razor.cs index cef62e56..3dd404ff 100644 --- a/BlazorAppTest/Pages/HxListLayoutTest.razor.cs +++ b/BlazorAppTest/Pages/HxListLayoutTest.razor.cs @@ -9,7 +9,6 @@ public partial class HxListLayoutTest private DataItemDto currentItem; private FilterModelDto filterModel = new FilterModelDto(); - private NamedView selectedNamedView; private HxGrid gridComponent; private readonly IEnumerable> namedViews = new List>() @@ -49,15 +48,8 @@ private Task> LoadDataItems(GridDataProvider }); } - private async Task HandleFilterModelChanged(FilterModelDto newFilterModel) + private async Task RefreshDataAsync() { - filterModel = newFilterModel; - await gridComponent.RefreshDataAsync(); - } - - protected async Task HandleSelectedNamedViewChanged() - { - filterModel = selectedNamedView.Filter(); await gridComponent.RefreshDataAsync(); } diff --git a/Havit.Blazor.Components.Web.Bootstrap/Layouts/HxListLayout.razor b/Havit.Blazor.Components.Web.Bootstrap/Layouts/HxListLayout.razor index 8e15805f..24107c5c 100644 --- a/Havit.Blazor.Components.Web.Bootstrap/Layouts/HxListLayout.razor +++ b/Havit.Blazor.Components.Web.Bootstrap/Layouts/HxListLayout.razor @@ -5,35 +5,50 @@
- @if (NamedViewsTemplate != null) - { -
- + } + else if (TitleTemplate != null) + { +
@TitleTemplate
+ } + else if (!String.IsNullOrEmpty(Title)) + { +
@Title
+ } @if (SearchTemplate != null) { @SearchTemplate @@ -56,12 +71,12 @@ + Id="@filterFormId" + TModel="TFilterModel" + Model="FilterModel" + ModelChanged="HandleFilterFormModelChanged" + Context="filterContext" + OnChipsUpdated="HandleChipUpdated"> @FilterTemplate(filterContext) diff --git a/Havit.Blazor.Components.Web.Bootstrap/Layouts/HxListLayout.razor.cs b/Havit.Blazor.Components.Web.Bootstrap/Layouts/HxListLayout.razor.cs index 45ee3197..62d6d4cf 100644 --- a/Havit.Blazor.Components.Web.Bootstrap/Layouts/HxListLayout.razor.cs +++ b/Havit.Blazor.Components.Web.Bootstrap/Layouts/HxListLayout.razor.cs @@ -3,7 +3,7 @@ namespace Havit.Blazor.Components.Web.Bootstrap; /// -/// Data presentation component composed of for data, for manual filtering, and for pre-defined filters.
+/// Data presentation component composed of for data, for manual filtering, and named-views for pre-defined filters.
/// Full documentation and demos: https://havit.blazor.eu/components/HxListLayout ///
/// @@ -28,11 +28,49 @@ public partial class HxListLayout /// protected virtual ListLayoutSettings GetSettings() => this.Settings; + /// + /// Title of the component. + /// If is true and is not null, the component's title displays the name of the currently selected Named View. + /// [Parameter] public string Title { get; set; } + /// + /// Title of the component (in form of RenderFragment). + /// If is true and is not null, the component's title displays the name of the currently selected Named View. + /// [Parameter] public RenderFragment TitleTemplate { get; set; } - [Parameter] public RenderFragment NamedViewsTemplate { get; set; } + /// + /// Represents the collection of Named Views available for selection. + /// Each Named View defines a pre-set filter configuration that can be applied to the data. + /// + /// + /// Named Views provide a convenient way for users to quickly apply commonly used filters to the data set. + /// Ensure that each Named View in the collection has a unique name which accurately describes its filter criteria. + /// + [Parameter] public IEnumerable> NamedViews { get; set; } + + /// + /// Selected named view (highlighted in the list with .active CSS class). + /// + [Parameter] public NamedView SelectedNamedView { get; set; } + [Parameter] public EventCallback> SelectedNamedViewChanged { get; set; } + /// + /// Triggers the event. Allows interception of the event in derived components. + /// + protected virtual Task InvokeSelectedNamedViewChangedAsync(NamedView itemSelected) => SelectedNamedViewChanged.InvokeAsync(itemSelected); + + /// + /// Indicates whether the name of the selected Named View () is automatically used as title. + /// If true, the component's title changes to match the name of the currently selected Named View. + /// Useful for dynamic title updates based on user selections from predefined views. + /// The default value is true. + /// + /// + /// This update occurs upon the selection of a new Named View. It allows the Title to reflect the + /// current data filtering context provided by the Named Views, enhancing user understanding of the active filter. + /// + [Parameter] public bool TitleFromNamedView { get; set; } = true; [Parameter] public RenderFragment SearchTemplate { get; set; } @@ -116,4 +154,17 @@ private async Task HandleFilterFormModelChanged(TFilterModel newFilterModel) await InvokeFilterModelChangedAsync(newFilterModel); await filterOffcanvasComponent.HideAsync(); } + + private async Task HandleNamedViewClickAsync(NamedView namedView) + { + SelectedNamedView = namedView; + await InvokeSelectedNamedViewChangedAsync(namedView); + + TFilterModel newFilterModel = namedView.FilterModelFactory(); + if (newFilterModel != null) + { + FilterModel = newFilterModel; + await InvokeFilterModelChangedAsync(newFilterModel); + } + } } diff --git a/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor b/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor deleted file mode 100644 index 2cec3fac..00000000 --- a/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor +++ /dev/null @@ -1,24 +0,0 @@ -@namespace Havit.Blazor.Components.Web.Bootstrap -@typeparam TItem - -@if ((Items != null) && Items.Any()) -{ - -} \ No newline at end of file diff --git a/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor.cs b/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor.cs deleted file mode 100644 index 1570ab1f..00000000 --- a/Havit.Blazor.Components.Web.Bootstrap/NamedViews/HxNamedViewList.razor.cs +++ /dev/null @@ -1,52 +0,0 @@ -namespace Havit.Blazor.Components.Web.Bootstrap; - -/// -/// List of named-views for .
-/// Full documentation and demos: https://havit.blazor.eu/components/HxListLayout#named-views -///
-public partial class HxNamedViewList -{ - /// - /// The items to display. - /// - [Parameter, EditorRequired] public IEnumerable Items { get; set; } - - /// - /// Selected item (highlighted in the list with .active CSS class). - /// - [Parameter] public TItem SelectedItem { get; set; } - [Parameter] public EventCallback SelectedItemChanged { get; set; } - /// - /// Triggers the event. Allows interception of the event in derived components. - /// - protected virtual Task InvokeSelectedItemChangedAsync(TItem itemSelected) => SelectedItemChanged.InvokeAsync(itemSelected); - - /// - /// Selects the text to display from the item. - /// You must set either this parameter or . - /// There is a special case when TItem is - in that case, the is used as the default text selector. - /// - [Parameter] public Func TextSelector { get; set; } - - /// - /// The template that defines how items in the component are displayed (optional). - /// You must set either this parameter or . - /// - [Parameter] public RenderFragment ItemTemplate { get; set; } - - protected override void OnParametersSet() - { - if ((TextSelector == null) && (ItemTemplate == null)) - { - // special case for NamedView - if (typeof(TItem).IsGenericType && (typeof(TItem).GetGenericTypeDefinition() == typeof(NamedView<>))) - { - TextSelector = item => (string)typeof(TItem).GetProperty(nameof(NamedView.Name)).GetValue(item); - } - else - { - throw new InvalidOperationException($"Either {nameof(TextSelector)} or {nameof(ItemTemplate)} must be set."); - } - } - } -} diff --git a/Havit.Blazor.Components.Web.Bootstrap/NamedViews/NamedView.cs b/Havit.Blazor.Components.Web.Bootstrap/NamedViews/NamedView.cs index 2159de42..4b7e27fd 100644 --- a/Havit.Blazor.Components.Web.Bootstrap/NamedViews/NamedView.cs +++ b/Havit.Blazor.Components.Web.Bootstrap/NamedViews/NamedView.cs @@ -1,24 +1,28 @@ namespace Havit.Blazor.Components.Web.Bootstrap; +/// +/// Represents a named view for . +/// public class NamedView { + /// + /// Name of the view. Used as a label in the list. Can be used as a title for the . + /// public string Name { get; } - public Func Filter { get; } + /// + /// Creates new filter model for the view. + /// + public Func FilterModelFactory { get; } - public NamedView(string name) : this(name, () => default) - { - // NOOP - } - - public NamedView(string name, TFilterModel filter) : this(name, () => filter) - { - // NOOP - } - - public NamedView(string name, Func filterFunc) + /// + /// Creates a new instance of which uses a factory to build a filter model. + /// + /// Name of the view. + /// Function which builds a new filter model to be applied when the view is selected. + public NamedView(string name, Func filterModelFactory) { Name = name; - Filter = filterFunc; + FilterModelFactory = filterModelFactory; } } diff --git a/Havit.Blazor.Documentation/Pages/Components/HxListLayoutDoc/HxListLayout_Demo_NamedViews.razor b/Havit.Blazor.Documentation/Pages/Components/HxListLayoutDoc/HxListLayout_Demo_NamedViews.razor index 9e7d6733..6140f05e 100644 --- a/Havit.Blazor.Documentation/Pages/Components/HxListLayoutDoc/HxListLayout_Demo_NamedViews.razor +++ b/Havit.Blazor.Documentation/Pages/Components/HxListLayoutDoc/HxListLayout_Demo_NamedViews.razor @@ -1,9 +1,13 @@ - - - - +@using Havit.Linq + + @@ -34,22 +38,20 @@ + + @code { - [Inject] protected NavigationManager NavigationManager { get; set; } + [Inject] protected NavigationManager NavigationManager { get; set; } - private EditableCultureInfo currentItem; - private FilterModelDto filterModel = new FilterModelDto(); - private HxGrid gridComponent; - private NamedView selectedNamedView; + private EditableCultureInfo currentItem; + private FilterModelDto filterModel = new FilterModelDto(); + private HxGrid gridComponent; + private NamedView selectedNamedView; + private bool titleFromNamedView = true; - private readonly IEnumerable> namedViews = new List>() - { - new NamedView("Minimum = 1", () => new FilterModelDto { MinimumLCID = 1 } ), - new NamedView("Minimum = 50", () => new FilterModelDto { MinimumLCID = 50 }), - new NamedView("Minimum = 100", () => new FilterModelDto { MinimumLCID = 100 }) - }; + private IEnumerable> namedViews; - private List localEditableCultureInfos = CultureInfo.GetCultures(CultureTypes.AllCultures).Select(c => new EditableCultureInfo() + private List localEditableCultureInfos = CultureInfo.GetCultures(CultureTypes.AllCultures).Select(c => new EditableCultureInfo() { LCID = c.LCID, DisplayName = c.DisplayName, @@ -57,22 +59,32 @@ EnglishName = c.EnglishName }).ToList(); - private Task> LoadDataItems(GridDataProviderRequest request) - { - IEnumerable result = localEditableCultureInfos.Where(i => i.LCID >= filterModel.MinimumLCID).ToList(); + protected override void OnInitialized() + { + namedViews = new List>() + { + new NamedView("Default view", () => new FilterModelDto()), // resets the filter + new NamedView("Minimum = 1", () => filterModel with { MinimumLCID = 1 } ), // keep filter presets not affected by the view + new NamedView("Minimum = 50", () => filterModel with { MinimumLCID = 50 }), + new NamedView("Minimum = 100", () => filterModel with { MinimumLCID = 100 }) + }; + + selectedNamedView = namedViews.First(); // set first view selected on initial load + } - return Task.FromResult(request.ApplyTo(result)); - } + private Task> LoadDataItems(GridDataProviderRequest request) + { + IEnumerable result = localEditableCultureInfos + .WhereIf(filterModel.MinimumLCID.HasValue, i => i.LCID >= filterModel.MinimumLCID) + .WhereIf(filterModel.MaximumLCID.HasValue, i => i.LCID <= filterModel.MaximumLCID) + .ToList(); - private async Task RefreshDataAsync() - { - await gridComponent.RefreshDataAsync(); - } + return Task.FromResult(request.ApplyTo(result)); + } - protected async Task HandleSelectedNamedViewChanged() - { - filterModel = selectedNamedView.Filter(); - await gridComponent.RefreshDataAsync(); + private async Task RefreshDataAsync() + { + await gridComponent.RefreshDataAsync(); } private async Task DeleteItemClicked(EditableCultureInfo editableCultureInfo) @@ -96,7 +108,8 @@ public record FilterModelDto { - public int MinimumLCID { get; set; } + public int? MinimumLCID { get; set; } + public int? MaximumLCID { get; set; } } private record EditableCultureInfo diff --git a/Havit.Blazor.Documentation/Pages/Components/HxNamedViewListDoc/HxNamedViewList_Documentation.razor b/Havit.Blazor.Documentation/Pages/Components/HxNamedViewListDoc/HxNamedViewList_Documentation.razor deleted file mode 100644 index edf1ffa2..00000000 --- a/Havit.Blazor.Documentation/Pages/Components/HxNamedViewListDoc/HxNamedViewList_Documentation.razor +++ /dev/null @@ -1,6 +0,0 @@ -@attribute [Route("/components/" + nameof(HxNamedViewList))] - - - - Use HxNamedViewList inside of HxListLayout. - \ No newline at end of file diff --git a/Havit.Blazor.Documentation/Shared/Sidebar.razor b/Havit.Blazor.Documentation/Shared/Sidebar.razor index 9c1df282..f2d5ca21 100644 --- a/Havit.Blazor.Documentation/Shared/Sidebar.razor +++ b/Havit.Blazor.Documentation/Shared/Sidebar.razor @@ -170,7 +170,6 @@ - )}")" Text="@(nameof(HxNamedViewList))" /> diff --git a/Havit.Blazor.Documentation/XmlDoc/Havit.Blazor.Components.Web.Bootstrap.xml b/Havit.Blazor.Documentation/XmlDoc/Havit.Blazor.Components.Web.Bootstrap.xml index 7bc729ff..264816d4 100644 --- a/Havit.Blazor.Documentation/XmlDoc/Havit.Blazor.Components.Web.Bootstrap.xml +++ b/Havit.Blazor.Documentation/XmlDoc/Havit.Blazor.Components.Web.Bootstrap.xml @@ -6864,7 +6864,7 @@ - Data presentation component composed of for data, for manual filtering, and for pre-defined filters.
+ Data presentation component composed of for data, for manual filtering, and named-views for pre-defined filters.
Full documentation and demos: https://havit.blazor.eu/components/HxListLayout
@@ -6888,6 +6888,50 @@ Similar to , enables defining wider in component descendants (by returning a derived settings class).
+ + + Title of the component. + If is true and is not null, the component's title displays the name of the currently selected Named View. + + + + + Title of the component (in form of RenderFragment). + If is true and is not null, the component's title displays the name of the currently selected Named View. + + + + + Represents the collection of Named Views available for selection. + Each Named View defines a pre-set filter configuration that can be applied to the data. + + + Named Views provide a convenient way for users to quickly apply commonly used filters to the data set. + Ensure that each Named View in the collection has a unique name which accurately describes its filter criteria. + + + + + Selected named view (highlighted in the list with .active CSS class). + + + + + Triggers the event. Allows interception of the event in derived components. + + + + + Indicates whether the name of the selected Named View () is automatically used as title. + If true, the component's title changes to match the name of the currently selected Named View. + Useful for dynamic title updates based on user selections from predefined views. + The default value is true. + + + This update occurs upon the selection of a new Named View. It allows the Title to reflect the + current data filtering context provided by the Named Views, enhancing user understanding of the active filter. + + Triggers the event. Allows interception of the event in derived components. @@ -7719,39 +7763,27 @@ Extra large. Modal max-width: 1140px. - + - List of named-views for .
- Full documentation and demos: https://havit.blazor.eu/components/HxListLayout#named-views + Represents a named view for .
- + - The items to display. + Name of the view. Used as a label in the list. Can be used as a title for the . - + - Selected item (highlighted in the list with .active CSS class). - - - - - Triggers the event. Allows interception of the event in derived components. - - - - - Selects the text to display from the item. - You must set either this parameter or . - There is a special case when TItem is - in that case, the is used as the default text selector. + Creates new filter model for the view. - + - The template that defines how items in the component are displayed (optional). - You must set either this parameter or . + Creates a new instance of which uses a factory to build a filter model. + Name of the view. + Function which builds a new filter model to be applied when the view is selected.