diff --git a/src/BootstrapBlazor.Shared/Samples/Tooltips.razor b/src/BootstrapBlazor.Shared/Samples/Tooltips.razor index 1ebc59e3c60d689d348744fb693743dc17d23496..4224f86ff16ddde093d5f1d8616f9537a9a740f0 100644 --- a/src/BootstrapBlazor.Shared/Samples/Tooltips.razor +++ b/src/BootstrapBlazor.Shared/Samples/Tooltips.razor @@ -53,8 +53,8 @@ -

@Localizer["P7"]

-

@Localizer["P8"]

+

@((MarkupString)Localizer["P7"].Value)

+

@((MarkupString)Localizer["P8"].Value)

<BootstrapTooltip Title="Test tooltip">
     <i class="fa-solid fa-flag" />
 </BootstrapTooltip>
diff --git a/src/BootstrapBlazor/Components/BaseComponents/BootstrapModuleComponentBase.cs b/src/BootstrapBlazor/Components/BaseComponents/BootstrapModuleComponentBase.cs index 2746f5c394094faf94127595d5c931eff14810d7..35b1d551e6f6277fae3a0d9b51df921bf06fc79e 100644 --- a/src/BootstrapBlazor/Components/BaseComponents/BootstrapModuleComponentBase.cs +++ b/src/BootstrapBlazor/Components/BaseComponents/BootstrapModuleComponentBase.cs @@ -36,13 +36,21 @@ public abstract class BootstrapModuleComponentBase : IdComponentBase, IAsyncDisp var type = this.GetType(); var attr = type.GetCustomAttribute(); - string? typeName = null; if (attr != null) { - ModulePath = attr.Path ?? GetTypeName().ToLowerInvariant(); - ModuleName = attr.ModuleName ?? GetTypeName(); - Relative = attr.Relative; + LoadModule(type, attr.Path, attr.ModuleName, attr.Relative); } + } + + /// + /// 加载本类模块 + /// + protected virtual void LoadModule(Type type, string? path, string? name, bool relative = true) + { + string? typeName = null; + ModulePath = path ?? GetTypeName().ToLowerInvariant(); + ModuleName = name ?? GetTypeName(); + Relative = relative; string GetTypeName() { diff --git a/src/BootstrapBlazor/Components/Tooltip/Tooltip.razor b/src/BootstrapBlazor/Components/Tooltip/Tooltip.razor index f04b9eb7dbbefeb9a8f25697d8a4627f59e587fb..a81c827ec9e8c63728696a324b3d3297e7432a66 100644 --- a/src/BootstrapBlazor/Components/Tooltip/Tooltip.razor +++ b/src/BootstrapBlazor/Components/Tooltip/Tooltip.razor @@ -1,8 +1,8 @@ @namespace BootstrapBlazor.Components -@inherits IdComponentBase +@inherits BootstrapModuleComponentBase @ChildContent diff --git a/src/BootstrapBlazor/Components/Tooltip/Tooltip.razor.cs b/src/BootstrapBlazor/Components/Tooltip/Tooltip.razor.cs index 7f6f0027ed1d9e1af94b6e046e705260e8885876..c40a64d59af633fd9e845f9817253afc88f21163 100644 --- a/src/BootstrapBlazor/Components/Tooltip/Tooltip.razor.cs +++ b/src/BootstrapBlazor/Components/Tooltip/Tooltip.razor.cs @@ -7,7 +7,8 @@ namespace BootstrapBlazor.Components; /// /// BootstrapTooltip 组件 /// -public partial class Tooltip : ITooltip, IAsyncDisposable +[JSModuleAutoLoader] +public partial class Tooltip : ITooltip { /// /// 弹窗位置字符串 @@ -112,17 +113,6 @@ public partial class Tooltip : ITooltip, IAsyncDisposable Trigger ??= "focus hover"; } - /// - /// - /// - /// - protected override async Task OnAfterRenderAsync(bool firstRender) - { - await base.OnAfterRenderAsync(firstRender); - - await JSInvokeAsync(); - } - /// /// 设置参数方法 /// @@ -143,34 +133,17 @@ public partial class Tooltip : ITooltip, IAsyncDisposable /// JavaScript invoke /// /// - protected virtual async ValueTask JSInvokeAsync() - { - if (!string.IsNullOrEmpty(Title)) - { - await JSRuntime.InvokeVoidByIdAsync(identifier: "bb.Tooltip.init", Id, Title); - } - } + protected virtual ValueTask JSInvokeAsync() => ValueTask.CompletedTask; /// - /// DisposeAsync 方法 + /// /// - /// /// - protected virtual async ValueTask DisposeAsync(bool disposing) + protected override async Task ModuleInitAsync() { - if (disposing) + if (Module != null) { - await JSRuntime.InvokeVoidByIdAsync(identifier: "bb.Tooltip.dispose", Id); + await Module.InvokeVoidAsync(identifier: $"{ModuleName}.init", Id, Title); } } - - /// - /// DisposeAsync 方法 - /// - /// - public async ValueTask DisposeAsync() - { - await DisposeAsync(true); - GC.SuppressFinalize(this); - } } diff --git a/src/BootstrapBlazor/Components/Validate/ValidateBase.cs b/src/BootstrapBlazor/Components/Validate/ValidateBase.cs index 00065c8cf050e36beaf5d75b3d7839cc18d587fa..6e51cf61664dca9448f5b22e4d54afd5b81b57c3 100644 --- a/src/BootstrapBlazor/Components/Validate/ValidateBase.cs +++ b/src/BootstrapBlazor/Components/Validate/ValidateBase.cs @@ -281,6 +281,9 @@ public abstract class ValidateBase : DisplayBase, IValidateCompo if (ValidateForm != null && FieldIdentifier.HasValue) { ValidateForm.AddValidator((FieldIdentifier.Value.FieldName, ModelType: FieldIdentifier.Value.Model.GetType()), (FieldIdentifier.Value, this)); + + // auto load module + LoadModule(this.GetType(), "tooltip", "Tooltip"); } } @@ -302,23 +305,21 @@ public abstract class ValidateBase : DisplayBase, IValidateCompo { await base.OnAfterRenderAsync(firstRender); - if (!firstRender) + if (!firstRender && IsValid.HasValue) { - if (IsValid.HasValue) + var valid = IsValid.Value; + IsValid = null; + if (valid) { - var valid = IsValid.Value; - IsValid = null; - if (valid) - { - await RemoveValidResult(); - } - else - { - await ShowValidResult(); - } + await RemoveValidResult(); + } + else + { + await ShowValidResult(); } } } + #region Validation /// /// 获得 数据验证方法集合 @@ -460,9 +461,9 @@ public abstract class ValidateBase : DisplayBase, IValidateCompo protected virtual async ValueTask ShowValidResult() { var id = RetrieveId(); - if (!string.IsNullOrEmpty(id) && !string.IsNullOrEmpty(ErrorMessage)) + if (!string.IsNullOrEmpty(id) && !string.IsNullOrEmpty(ErrorMessage) && Module != null) { - await JSRuntime.InvokeVoidByIdAsync(identifier: "bb.Tooltip.init", id, ErrorMessage); + await Module.InvokeVoidAsync($"{ModuleName}.init", id, ErrorMessage, "Valid"); } } @@ -473,9 +474,9 @@ public abstract class ValidateBase : DisplayBase, IValidateCompo protected virtual async ValueTask RemoveValidResult() { var id = RetrieveId(); - if (!string.IsNullOrEmpty(id)) + if (!string.IsNullOrEmpty(id) && Module != null) { - await JSRuntime.InvokeVoidByIdAsync(identifier: "bb.Tooltip.dispose", id); + await Module.InvokeVoidAsync($"{ModuleName}.dispose", id); } } @@ -485,11 +486,7 @@ public abstract class ValidateBase : DisplayBase, IValidateCompo /// 检查结果 protected virtual void OnValidate(bool? valid) { - if (valid.HasValue) - { - AdditionalAttributes ??= new Dictionary(); - AdditionalAttributes["aria-invalid"] = valid.Value ? "false" : "true"; - } + } /// @@ -505,11 +502,6 @@ public abstract class ValidateBase : DisplayBase, IValidateCompo { ValidateForm.TryRemoveValidator((FieldIdentifier.Value.FieldName, FieldIdentifier.Value.Model.GetType()), out _); } - - if (IsValid.HasValue && !IsValid.Value) - { - await RemoveValidResult(); - } } await base.DisposeAsync(disposing); diff --git a/src/BootstrapBlazor/wwwroot/modules/base/blazor-component.js b/src/BootstrapBlazor/wwwroot/modules/base/blazor-component.js index 332801acebf21ae49e0f2a2852c7775af933ada6..ba203601b448d25da2b3ac72d44724c23bd35ad8 100644 --- a/src/BootstrapBlazor/wwwroot/modules/base/blazor-component.js +++ b/src/BootstrapBlazor/wwwroot/modules/base/blazor-component.js @@ -49,7 +49,7 @@ class BlazorComponent extends BaseComponent { static execute(element) { element = getElementById(element) if (element) { - var instance = this.getInstance(element) + const instance = this.getInstance(element) instance._execute([].slice.call(arguments, 1)) } } diff --git a/src/BootstrapBlazor/wwwroot/modules/menu.js b/src/BootstrapBlazor/wwwroot/modules/menu.js index 3a7009e95ce662d3969a2fc46e7be861a2c29a25..1221949195cd49f20d078bcae897e83dd3255e49 100644 --- a/src/BootstrapBlazor/wwwroot/modules/menu.js +++ b/src/BootstrapBlazor/wwwroot/modules/menu.js @@ -1,7 +1,7 @@ import BlazorComponent from "./base/blazor-component.js"; import { getTargetElement, getTransitionDelayDurationFromElement } from "./base/utility.js" -class Menu extends BlazorComponent { +export class Menu extends BlazorComponent { _init() { this._collapses = this._element.querySelectorAll('[data-bs-toggle="collapse"]') this._activeLink() @@ -80,7 +80,3 @@ class Menu extends BlazorComponent { }) } } - -export { - Menu -} diff --git a/src/BootstrapBlazor/wwwroot/modules/tooltip.js b/src/BootstrapBlazor/wwwroot/modules/tooltip.js new file mode 100644 index 0000000000000000000000000000000000000000..0597c5ed34117470de72aac6dd5ef05adeea3ef6 --- /dev/null +++ b/src/BootstrapBlazor/wwwroot/modules/tooltip.js @@ -0,0 +1,47 @@ +import BlazorComponent from "./base/blazor-component.js" +import { getTransitionDelayDurationFromElement } from "./base/utility.js" + +export class Tooltip extends BlazorComponent { + _init() { + this._config.title = this._config.arguments[1] + if (this._config.arguments.length > 2) { + const method = this._config.arguments[2] + if (method === 'Valid') { + this._reset() + } + } + else { + this._create() + } + } + + _reset() { + this._config.customClass = 'is-invalid' + this._tooltip = bootstrap.Tooltip.getInstance(this._element) + if (this._tooltip !== null && this._tooltip._isShown()) { + this._tooltip.hide(); + + const duration = getTransitionDelayDurationFromElement(this._element); + const handler = window.setTimeout(() => { + window.clearTimeout(handler); + this._tooltip.dispose(); + this._create(true); + }, duration); + } else { + this._create(true); + } + } + + _create(toggle = false) { + this._tooltip = new bootstrap.Tooltip(this._element, this._config) + if (toggle) { + this._tooltip.toggle() + } + } + + _dispose() { + if (this._tooltip && this._tooltip.tip !== null) { + this._tooltip.dispose(); + } + } +} diff --git a/src/BootstrapBlazor/wwwroot/modules/upload.js b/src/BootstrapBlazor/wwwroot/modules/upload.js index acf281744f08c5ee3e802802cc782616428e9d65..509553716c6ab165937d128626aeb7bfe03871d0 100644 --- a/src/BootstrapBlazor/wwwroot/modules/upload.js +++ b/src/BootstrapBlazor/wwwroot/modules/upload.js @@ -1,7 +1,7 @@ import EventHandler from "./base/event-handler.js" import BlazorComponent from "./base/blazor-component.js" -class Upload extends BlazorComponent { +export class Upload extends BlazorComponent { _init() { this._inputFile = this._element.querySelector('[type="file"]') this._setListeners() @@ -61,7 +61,3 @@ class Upload extends BlazorComponent { EventHandler.off(this._element, 'paste'); } } - -export { - Upload -}