From 6a3cbc9335f06c43edf8f8e8387612d41a6f65ec Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 7 Nov 2024 20:42:56 +0800 Subject: [PATCH] Fix #4778: update the tabstrip view after render. --- Oqtane.Client/Modules/Controls/TabStrip.razor | 58 ++++++++++++------- Oqtane.Client/UI/ControlsInterop.cs | 31 ++++++++++ Oqtane.Server/wwwroot/js/controls.interop.js | 17 ++++++ 3 files changed, 85 insertions(+), 21 deletions(-) create mode 100644 Oqtane.Client/UI/ControlsInterop.cs create mode 100644 Oqtane.Server/wwwroot/js/controls.interop.js diff --git a/Oqtane.Client/Modules/Controls/TabStrip.razor b/Oqtane.Client/Modules/Controls/TabStrip.razor index e2a3c0f16..7094187eb 100644 --- a/Oqtane.Client/Modules/Controls/TabStrip.razor +++ b/Oqtane.Client/Modules/Controls/TabStrip.razor @@ -16,7 +16,7 @@ } else { - + @tabPanel.DisplayHeading() } @@ -32,34 +32,43 @@ @code { - private List _tabPanels; - private string _tabpanelid = string.Empty; + public override List Resources { get; set; } = new List() + { + new Resource { ResourceType = ResourceType.Script, Url = "js/controls.interop.js", Location = ResourceLocation.Body } + }; - [Parameter] - public RenderFragment ChildContent { get; set; } // contains the TabPanels + private List _tabPanels; + private string _tabpanelid = string.Empty; - [Parameter] - public string ActiveTab { get; set; } // optional - defaults to first TabPanel if not specified. Can also be set using a "tab=" querystring parameter. + [Parameter] + public RenderFragment ChildContent { get; set; } // contains the TabPanels - [Parameter] - public bool Refresh { get; set; } // optional - used in scenarios where TabPanels are added/removed dynamically within a parent form. ActiveTab may need to be reset as well when this property is used. + [Parameter] + public string ActiveTab { get; set; } // optional - defaults to first TabPanel if not specified. Can also be set using a "tab=" querystring parameter. - [Parameter] - public string Id { get; set; } // optional - used to uniquely identify an instance of a tab strip component (will be set automatically if no value provided) + [Parameter] + public bool Refresh { get; set; } // optional - used in scenarios where TabPanels are added/removed dynamically within a parent form. ActiveTab may need to be reset as well when this property is used. + + [Parameter] + public string Id { get; set; } // optional - used to uniquely identify an instance of a tab strip component (will be set automatically if no value provided) [Parameter] public string TabContentClass { get; set; } // optional - to extend the TabContent div. - protected override void OnInitialized() - { - if (string.IsNullOrEmpty(Id)) - { - // create unique id for component - Id = "TabStrip_" + Guid.NewGuid().ToString("N") + "_" ; - } - } - - protected override void OnParametersSet() + private TabStripInterop _interop; + + protected override void OnInitialized() + { + if (string.IsNullOrEmpty(Id)) + { + // create unique id for component + Id = "TabStrip_" + Guid.NewGuid().ToString("N") + "_" ; + } + + _interop = new TabStripInterop(JSRuntime); + } + + protected override void OnParametersSet() { if (PageState.QueryString.ContainsKey("tab")) { @@ -110,4 +119,11 @@ } return authorized; } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + await base.OnAfterRenderAsync(firstRender); + + await _interop.UpdateView(Id); + } } diff --git a/Oqtane.Client/UI/ControlsInterop.cs b/Oqtane.Client/UI/ControlsInterop.cs new file mode 100644 index 000000000..e875d4a07 --- /dev/null +++ b/Oqtane.Client/UI/ControlsInterop.cs @@ -0,0 +1,31 @@ +using Microsoft.AspNetCore.Components; +using Microsoft.JSInterop; +using System.Threading.Tasks; +using System.Text.Json; +using System.Collections.Generic; +using System.Linq; + +namespace Oqtane.UI +{ + public class TabStripInterop + { + private readonly IJSRuntime _jsRuntime; + + public TabStripInterop(IJSRuntime jsRuntime) + { + _jsRuntime = jsRuntime; + } + + public async Task UpdateView(string id) + { + try + { + await _jsRuntime.InvokeVoidAsync("Oqtane.Controls.TabStrip.Interop.updateView",id); + } + catch + { + //do nothing here. + } + } + } +} diff --git a/Oqtane.Server/wwwroot/js/controls.interop.js b/Oqtane.Server/wwwroot/js/controls.interop.js new file mode 100644 index 000000000..62662bd59 --- /dev/null +++ b/Oqtane.Server/wwwroot/js/controls.interop.js @@ -0,0 +1,17 @@ +var Oqtane = Oqtane || {}; +Oqtane.Controls = Oqtane.Controls || {}; + +//interop functions for tabstrip control +Oqtane.Controls.TabStrip = Oqtane.Controls.TabStrip || {}; +Oqtane.Controls.TabStrip.Interop = { + updateView: function (id) { + var activeTab = document.querySelector('.nav-tabs .nav-item a.active[href^="#' + id + '"]'); + if (activeTab != null) { + var tabPanel = document.getElementById(activeTab.getAttribute("href").replace("#", "")); + if (tabPanel != null && !tabPanel.classList.contains("active")) { + document.querySelectorAll('div[id^="' + id + '"]').forEach(i => i.classList.remove('show', 'active')); + tabPanel.classList.add('show', 'active'); + } + } + } +};