diff --git a/src/BootstrapBlazor.Shared/Pages/Introduction.razor b/src/BootstrapBlazor.Shared/Pages/Introduction.razor
index 66e0936232b739c52327fa95a096a2552d98f45d..4399234f8537f8bf8c9d1791d17cfdff34020e6a 100644
--- a/src/BootstrapBlazor.Shared/Pages/Introduction.razor
+++ b/src/BootstrapBlazor.Shared/Pages/Introduction.razor
@@ -1,6 +1,7 @@
@page "/docs"
@page "/introduction"
@inject IOptions
WebsiteOption
+
简介
BootstrapBlazor 是一套基于 Bootstrap 和 Blazor 的企业级组件库,可以认为是 Bootstrap 项目的 Blazor 版实现。
diff --git a/src/BootstrapBlazor.Shared/Pages/Samples/Titles.razor b/src/BootstrapBlazor.Shared/Pages/Samples/Titles.razor
new file mode 100644
index 0000000000000000000000000000000000000000..666c4eb039a806034f4c00930bdf4271928a6585
--- /dev/null
+++ b/src/BootstrapBlazor.Shared/Pages/Samples/Titles.razor
@@ -0,0 +1,50 @@
+@page "/titles"
+
+Title 网站标题
+
+用于设置网页页面标题
+
+
+
+
+ Title 组件设置 Text 后为普通组件使用,未设置 Text 属性时供服务调用
+
+
+ 设置 Text 属性
+ @@page "/titles"
+<Title Text="我是标题" />
+<p>测试网页<p/>
+
+
+
+
+
+ 特别注意:
+
使用此种方法时请在 App 或者 MainLayout 或者 Page 中添加 未设置 Text 属性 的 Title 组件
+
+ [Inject]
+[NotNull]
+private TitleService? TitleService { get; set; }
+
+protected override async Task OnAfterRenderAsync(bool firstRender)
+{
+ await base.OnAfterRenderAsync(firstRender);
+
+ await TitleService.SetTitle("我是标题");
+}
+
+
+
+
+
+ 特别注意:
+
使用此种方法时请在 App 或者 MainLayout 或者 Page 中添加 未设置 Text 属性 的 Title 组件
+
+ protected override async Task OnAfterRenderAsync(bool firstRender)
+{
+ await base.OnAfterRenderAsync(firstRender);
+
+ await TitleService.SetWebSiteTitle("我是标题");
+}
+
+
diff --git a/src/BootstrapBlazor.Shared/Pages/Samples/Titles.razor.cs b/src/BootstrapBlazor.Shared/Pages/Samples/Titles.razor.cs
new file mode 100644
index 0000000000000000000000000000000000000000..a841cba7183e5dfa00fcc05f2f96efd358fff218
--- /dev/null
+++ b/src/BootstrapBlazor.Shared/Pages/Samples/Titles.razor.cs
@@ -0,0 +1,19 @@
+// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// Website: https://www.blazor.zone or https://argozhang.github.io/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BootstrapBlazor.Shared.Pages
+{
+ ///
+ /// Title 网站标题示例代码
+ ///
+ public partial class Title
+ {
+ }
+}
diff --git a/src/BootstrapBlazor.Shared/Shared/NavMenu.razor.cs b/src/BootstrapBlazor.Shared/Shared/NavMenu.razor.cs
index d485a7f76b1893ec1da1d4cc962a87d8a7526332..3fe1bc1ec31b7bb5039a8f39beafaf54c5143460 100644
--- a/src/BootstrapBlazor.Shared/Shared/NavMenu.razor.cs
+++ b/src/BootstrapBlazor.Shared/Shared/NavMenu.razor.cs
@@ -4,7 +4,10 @@
using BootstrapBlazor.Components;
using BootstrapBlazor.Shared.Pages.Components;
+using Microsoft.AspNetCore.Components;
+using Microsoft.Extensions.Localization;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading.Tasks;
@@ -17,6 +20,10 @@ namespace BootstrapBlazor.Shared.Shared
{
private bool collapseNavMenu = true;
+ [Inject]
+ [NotNull]
+ private IStringLocalizer? Localizer { get; set; }
+
private string? NavMenuCssClass => CssBuilder.Default("sidebar-content")
.AddClass("collapse", collapseNavMenu)
.Build();
@@ -40,6 +47,11 @@ namespace BootstrapBlazor.Shared.Shared
ToggleNavMenu();
StateHasChanged();
}
+
+ if (!string.IsNullOrEmpty(item.Text))
+ {
+ await TitleService.SetWebSiteTitle($"{item.Text} - {Localizer["Title"]}");
+ }
}
private void ToggleNavMenu()
@@ -372,6 +384,7 @@ namespace BootstrapBlazor.Shared.Shared
});
item.AddItem(new DemoMenuItem()
{
+ IsNew = true,
Text = "网站标题 Title",
Url = "titles"
});
diff --git a/src/BootstrapBlazor/Components/Title/Title.cs b/src/BootstrapBlazor/Components/Title/Title.cs
new file mode 100644
index 0000000000000000000000000000000000000000..8f21b9c238f61306c5cc647c882bb6c430bae4f0
--- /dev/null
+++ b/src/BootstrapBlazor/Components/Title/Title.cs
@@ -0,0 +1,75 @@
+// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// Website: https://www.blazor.zone or https://argozhang.github.io/
+
+using Microsoft.AspNetCore.Components;
+using Microsoft.JSInterop;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace BootstrapBlazor.Components
+{
+ ///
+ /// Title 组件
+ ///
+ public class Title : BootstrapComponentBase
+ {
+ [Inject]
+ [NotNull]
+ private TitleService? TitleService { get; set; }
+
+ ///
+ /// 获得/设置 当前页标题文字
+ ///
+ [Parameter]
+ public string? Text { get; set; }
+
+ ///
+ /// OnInitialized 方法
+ ///
+ protected override void OnInitialized()
+ {
+ base.OnInitialized();
+
+ if (string.IsNullOrEmpty(Text))
+ {
+ TitleService.Register(this, SetTitle);
+ }
+ }
+
+ ///
+ /// OnAfterRenderAsync 方法
+ ///
+ ///
+ ///
+ protected override async Task OnAfterRenderAsync(bool firstRender)
+ {
+ await base.OnAfterRenderAsync(firstRender);
+
+ if (!string.IsNullOrEmpty(Text))
+ {
+ await SetTitle(Text);
+ }
+ }
+
+ ///
+ /// 设置网站 Title 方法
+ ///
+ ///
+ ///
+ private ValueTask SetTitle(string title) => JSRuntime.InvokeVoidAsync(identifier: "$.bb_setTitle", title);
+
+ ///
+ /// Dispose 方法
+ ///
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+
+ if (disposing)
+ {
+ TitleService.UnRegister(this);
+ }
+ }
+ }
+}
diff --git a/src/BootstrapBlazor/Components/Title/Title.cs.js b/src/BootstrapBlazor/Components/Title/Title.cs.js
new file mode 100644
index 0000000000000000000000000000000000000000..5e25367b3c6498607b164d7b7bd4c349fba42cea
--- /dev/null
+++ b/src/BootstrapBlazor/Components/Title/Title.cs.js
@@ -0,0 +1,7 @@
+(function ($) {
+ $.extend({
+ bb_setTitle: function (title) {
+ document.title = title;
+ }
+ });
+})(jQuery);
diff --git a/src/BootstrapBlazor/Components/Title/Title.cs.min.js b/src/BootstrapBlazor/Components/Title/Title.cs.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..92099bfaeec6800514a3bf022bc05b1713228e3e
--- /dev/null
+++ b/src/BootstrapBlazor/Components/Title/Title.cs.min.js
@@ -0,0 +1 @@
+(function(n){n.extend({bb_setTitle:function(n){document.title=n}})})(jQuery);
\ No newline at end of file
diff --git a/src/BootstrapBlazor/Components/Title/TitleService.cs b/src/BootstrapBlazor/Components/Title/TitleService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..90a0404189396dfcac38a091fbde7842591b3da5
--- /dev/null
+++ b/src/BootstrapBlazor/Components/Title/TitleService.cs
@@ -0,0 +1,65 @@
+// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// Website: https://www.blazor.zone or https://argozhang.github.io/
+
+using Microsoft.AspNetCore.Components;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace BootstrapBlazor.Components
+{
+ ///
+ /// Title 服务
+ ///
+ public class TitleService
+ {
+ ///
+ /// 获得 回调委托缓存集合
+ ///
+ private List<(IComponent Key, Func Callback)> Cache { get; set; } = new();
+
+ ///
+ /// 设置当前页面 Title 方法
+ ///
+ ///
+ ///
+ public async ValueTask SetTitle(string title)
+ {
+ var cb = Cache.FirstOrDefault().Callback;
+ if (cb != null)
+ {
+ await cb.Invoke(title);
+ }
+ }
+
+ ///
+ /// 注册服务
+ ///
+ ///
+ ///
+ internal void Register(IComponent key, Func callback) => Cache.Add((key, callback));
+
+ ///
+ /// 注销事件
+ ///
+ internal void UnRegister(IComponent key)
+ {
+ var item = Cache.FirstOrDefault(i => i.Key == key);
+ if (item.Key != null) Cache.Remove(item);
+ }
+
+ ///
+ /// 设置网站标题方法
+ ///
+ ///
+ ///
+ public static ValueTask SetWebSiteTitle(string title)
+ {
+ var titleSvr = ServiceProviderHelper.ServiceProvider.GetRequiredService();
+ return titleSvr.SetTitle(title);
+ }
+ }
+}
diff --git a/src/BootstrapBlazor/Extensions/BootstrapBlazorServiceCollectionExtensions.cs b/src/BootstrapBlazor/Extensions/BootstrapBlazorServiceCollectionExtensions.cs
index bef35c448f256691f632810992a0bb58c59c21fe..3f80daa783dced03db513783951f3c89d8b85f66 100644
--- a/src/BootstrapBlazor/Extensions/BootstrapBlazorServiceCollectionExtensions.cs
+++ b/src/BootstrapBlazor/Extensions/BootstrapBlazorServiceCollectionExtensions.cs
@@ -35,6 +35,7 @@ namespace Microsoft.Extensions.DependencyInjection
services.TryAddScoped();
services.TryAddScoped();
services.TryAddScoped();
+ services.TryAddScoped();
services.TryAddSingleton, ConfigureOptions>();
services.Configure(options =>
{
diff --git a/src/BootstrapBlazor/bundleconfig.json b/src/BootstrapBlazor/bundleconfig.json
index e106a0d8fe52cace446a268831137e5eedeec9c4..f24808ce7b9f6ae70152328d53cc1d09d2dc732e 100644
--- a/src/BootstrapBlazor/bundleconfig.json
+++ b/src/BootstrapBlazor/bundleconfig.json
@@ -500,6 +500,12 @@
"Components/Table/Filter/TableFilter.razor.cs.js"
]
},
+ {
+ "outputFileName": "Components/Title/Title.cs.min.js",
+ "inputFiles": [
+ "Components/Title/Title.cs.js"
+ ]
+ },
{
"outputFileName": "Components/Toast/Toast.razor.cs.min.js",
"inputFiles": [
@@ -548,7 +554,7 @@
"Components/ColorPicker/ColorPicker.razor.cs.min.js",
"Components/Console/Console.razor.cs.min.js",
"Components/DateTimePicker/DateTimePicker.razor.cs.min.js",
- "Components/DateTimePicker/TimePickerBody.razor.cs.js",
+ "Components/DateTimePicker/TimePickerBody.razor.cs.min.js",
"Components/DateTimeRange/DateTimeRange.razor.cs.min.js",
"Components/Drawer/Drawer.razor.cs.min.js",
"Components/Editor/Editor.razor.cs.min.js",
@@ -568,6 +574,7 @@
"Components/Tab/Tab.razor.cs.min.js",
"Components/Table/Table.razor.cs.min.js",
"Components/Table/Filter/TableFilter.razor.cs.min.js",
+ "Components/Title/Title.cs.min.js",
"Components/Toast/Toast.razor.cs.min.js",
"Components/Tooltip/Tooltip.cs.min.js",
"Components/Tree/Tree.razor.cs.min.js",
diff --git a/src/BootstrapBlazor/wwwroot/js/bootstrap.blazor.bundle.min.js b/src/BootstrapBlazor/wwwroot/js/bootstrap.blazor.bundle.min.js
index b278aa258c195b1b7e8dddf5a45c3d8eba8daea5..d4546b3b8d7f5cbd95e71787c709d032e0b5fa5c 100644
--- a/src/BootstrapBlazor/wwwroot/js/bootstrap.blazor.bundle.min.js
+++ b/src/BootstrapBlazor/wwwroot/js/bootstrap.blazor.bundle.min.js
@@ -52,28 +52,7 @@ x();"bottom"===a.start?(c.css({top:b.outerHeight()-c.outerHeight()}),n(0,!0)):"t
(function(n){n.extend({bb_color_picker:function(t,i,r){n(t).colorpicker().on("change",function(n){i.invokeMethodAsync(r,n.value)})}})})(jQuery);
(function(n){n.extend({bb_console:function(t){var u=n(t),i=u.find('[data-scroll="auto"]'),r;i.length>0&&(r=i.find(".console-window"),i.scrollTop(r.height()))}})})(jQuery);
(function(n){n.extend({bb_datetimePicker:function(t,i){var r=n(t),f=r.attr("data-placement")||"auto",u=r.find(".datetime-picker-input");if(i)u.popover(i);else{u.popover({toggle:"datetime-picker",placement:f,template:'