Skip to content

Commit 809ede2

Browse files
authored
refactor(Modal): use BootstrapBlazorRootOutlet wrap Modal component (#5595)
* Revert "doc(Layout): remove man z-index attribute (#5540)" This reverts commit 096dc3f. * refactor: 移除 InvokeAsync 包裹 * refactor: 支持多个 provider 逻辑 * refactor: 使用 BootstrapBlazorRootContent 更改位置 * refactor: 重构 Swal 组件 * refactor: 更新文档注释 * doc: 更新文档注释 * refactor: 增加扩展属性 * style: 增加样式防止多层弹窗导致背景色加深 * refactor(Swal): 增加 swal 样式 * test: 更新单元测试 * test: 更新单元测试 * test: 更新单元测试 * test: 更新单元测试
1 parent 950d7b4 commit 809ede2

File tree

16 files changed

+153
-110
lines changed

16 files changed

+153
-110
lines changed

src/BootstrapBlazor.Server/Components/Layout/BaseLayout.razor.css

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@
66

77
main {
88
min-height: calc(100vh - var(--bs-header-height));
9+
position: relative;
10+
z-index: 10;
911
}

src/BootstrapBlazor.Server/Components/Layout/MainLayout.razor.css

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
.main {
66
padding: var(--bb-main-pading);
7+
position: relative;
8+
z-index: 5;
79
}
810

911
.sidebar-title {

src/BootstrapBlazor/Components/Dialog/Dialog.razor.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
5555
}
5656
}
5757

58-
private async Task Show(DialogOption option)
58+
private Task Show(DialogOption option)
5959
{
6060
_onShownAsync = async () =>
6161
{
@@ -158,7 +158,8 @@ private async Task Show(DialogOption option)
158158

159159
// Add ModalDialog to the container
160160
DialogParameters.Add(parameters, (_isKeyboard, _isBackdrop));
161-
await InvokeAsync(StateHasChanged);
161+
StateHasChanged();
162+
return Task.CompletedTask;
162163
}
163164

164165
private static RenderFragment RenderDialog(int index, Dictionary<string, object> parameter) => builder =>

src/BootstrapBlazor/Components/Modal/Modal.razor

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
@inherits BootstrapModuleComponentBase
33
@attribute [BootstrapModuleAutoLoader(JSObjectReference = true)]
44

5-
<div @attributes="@AdditionalAttributes" class="@ClassString" tabindex="-1" role="dialog" data-bs-backdrop="@Backdrop" data-bs-keyboard="@KeyboardString" id="@Id">
6-
<CascadingValue Value="this" IsFixed="true">
7-
@ChildContent
8-
</CascadingValue>
9-
</div>
5+
<BootstrapBlazorRootContent>
6+
<div @attributes="@AdditionalAttributes" class="@ClassString" tabindex="-1" role="dialog" data-bs-backdrop="@Backdrop" data-bs-keyboard="@KeyboardString" id="@Id">
7+
<CascadingValue Value="this" IsFixed="true">
8+
@ChildContent
9+
</CascadingValue>
10+
</div>
11+
</BootstrapBlazorRootContent>

src/BootstrapBlazor/Components/Modal/Modal.razor.cs

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,68 +8,69 @@
88
namespace BootstrapBlazor.Components;
99

1010
/// <summary>
11-
/// Modal 组件
11+
/// Modal component
1212
/// </summary>
1313
public partial class Modal
1414
{
1515
/// <summary>
16-
/// 获得 样式字符串
16+
/// Gets the style string
1717
/// </summary>
1818
private string? ClassString => CssBuilder.Default("modal")
1919
.AddClass("fade", IsFade)
20+
.AddClassFromAttributes(AdditionalAttributes)
2021
.Build();
2122

2223
/// <summary>
23-
/// 获得 ModalDialog 集合
24+
/// Gets the collection of ModalDialog
2425
/// </summary>
2526
protected List<ModalDialog> Dialogs { get; } = new(8);
2627

2728
private readonly ConcurrentDictionary<IComponent, Func<Task>> _shownCallbackCache = [];
2829

2930
/// <summary>
30-
/// 获得/设置 是否后台关闭弹窗 默认 false
31+
/// Gets or sets whether to close the popup in the background, default is false
3132
/// </summary>
3233
[Parameter]
3334
public bool IsBackdrop { get; set; }
3435

3536
/// <summary>
36-
/// 获得/设置 是否开启键盘支持 默认 true 响应键盘 ESC 按键
37+
/// Gets or sets whether to enable keyboard support, default is true to respond to the ESC key
3738
/// </summary>
3839
[Parameter]
3940
public bool IsKeyboard { get; set; } = true;
4041

4142
/// <summary>
42-
/// 获得/设置 是否开启淡入淡出动画 默认为 true 开启动画
43+
/// Gets or sets whether to enable fade in and out animation, default is true to enable animation
4344
/// </summary>
4445
[Parameter]
4546
public bool IsFade { get; set; } = true;
4647

4748
/// <summary>
48-
/// 获得/设置 子组件
49+
/// Gets or sets the child component
4950
/// </summary>
5051
[Parameter]
5152
public RenderFragment? ChildContent { get; set; }
5253

5354
/// <summary>
54-
/// 获得/设置 组件已经渲染完毕回调方法
55+
/// Gets or sets the callback method when the component has finished rendering
5556
/// </summary>
5657
[Parameter]
5758
public Func<Modal, Task>? FirstAfterRenderCallbackAsync { get; set; }
5859

5960
/// <summary>
60-
/// 获得/设置 弹窗已显示时回调此方法
61+
/// Gets or sets the callback method when the popup is shown
6162
/// </summary>
6263
[Parameter]
6364
public Func<Task>? OnShownAsync { get; set; }
6465

6566
/// <summary>
66-
/// 获得/设置 关闭弹窗回调委托
67+
/// Gets or sets the callback delegate when the popup is closed
6768
/// </summary>
6869
[Parameter]
6970
public Func<Task>? OnCloseAsync { get; set; }
7071

7172
/// <summary>
72-
/// 获得 后台关闭弹窗设置
73+
/// Gets the background close popup setting
7374
/// </summary>
7475
private string? Backdrop => IsBackdrop ? null : "static";
7576

@@ -97,7 +98,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
9798
protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Interop, nameof(ShownCallback), nameof(CloseCallback));
9899

99100
/// <summary>
100-
/// 添加对话框方法
101+
/// Method to add a dialog
101102
/// </summary>
102103
/// <param name="dialog"></param>
103104
internal void AddDialog(ModalDialog dialog)
@@ -107,12 +108,12 @@ internal void AddDialog(ModalDialog dialog)
107108
}
108109

109110
/// <summary>
110-
/// 移除对话框方法
111+
/// Method to remove a dialog
111112
/// </summary>
112113
/// <param name="dialog"></param>
113114
internal void RemoveDialog(ModalDialog dialog)
114115
{
115-
// 移除当前弹窗
116+
// Remove the current popup
116117
Dialogs.Remove(dialog);
117118

118119
if (Dialogs.Count > 0)
@@ -123,15 +124,15 @@ internal void RemoveDialog(ModalDialog dialog)
123124

124125
private void ResetShownDialog(ModalDialog dialog)
125126
{
126-
// 保证新添加的 Dialog 为当前弹窗
127+
// Ensure the newly added Dialog is the current popup
127128
Dialogs.ForEach(d =>
128129
{
129130
d.IsShown = d == dialog;
130131
});
131132
}
132133

133134
/// <summary>
134-
/// 弹窗已经弹出回调方法 JSInvoke 调用
135+
/// Callback method when the popup has been shown, called by JSInvoke
135136
/// </summary>
136137
/// <returns></returns>
137138
[JSInvokable]
@@ -149,20 +150,20 @@ public async Task ShownCallback()
149150
}
150151

151152
/// <summary>
152-
/// 弹窗已经关闭回调方法 JSInvoke 调用
153+
/// Callback method when the popup has been closed, called by JSInvoke
153154
/// </summary>
154155
/// <returns></returns>
155156
[JSInvokable]
156157
public async Task CloseCallback()
157158
{
158-
// 移除当前弹窗
159+
// Remove the current popup
159160
var dialog = Dialogs.FirstOrDefault(d => d.IsShown);
160161
if (dialog != null)
161162
{
162163
Dialogs.Remove(dialog);
163164
}
164165

165-
// 多级弹窗支持
166+
// Support for multi-level popups
166167
if (Dialogs.Count > 0)
167168
{
168169
ResetShownDialog(Dialogs.Last());
@@ -175,7 +176,7 @@ public async Task CloseCallback()
175176
}
176177

177178
/// <summary>
178-
/// 弹窗状态切换方法
179+
/// Method to toggle the popup state
179180
/// </summary>
180181
public async Task Toggle()
181182
{
@@ -184,7 +185,7 @@ public async Task Toggle()
184185
}
185186

186187
/// <summary>
187-
/// 显示弹窗方法
188+
/// Method to show the popup
188189
/// </summary>
189190
/// <returns></returns>
190191
public async Task Show()
@@ -194,13 +195,13 @@ public async Task Show()
194195
}
195196

196197
/// <summary>
197-
/// 关闭当前弹窗方法
198+
/// Method to close the current popup
198199
/// </summary>
199200
/// <returns></returns>
200201
public Task Close() => InvokeVoidAsync("execute", Id, "hide");
201202

202203
/// <summary>
203-
/// 设置 Header 文字方法
204+
/// Method to set the header text
204205
/// </summary>
205206
/// <param name="text"></param>
206207
public void SetHeaderText(string text)
@@ -210,19 +211,19 @@ public void SetHeaderText(string text)
210211
}
211212

212213
/// <summary>
213-
/// 注册弹窗显示后回调方法,供代码调用等效 OnShownAsync 参数赋值
214+
/// Registers a callback method to be called after the popup is shown, equivalent to setting the OnShownAsync parameter
214215
/// </summary>
215-
/// <param name="component">组件</param>
216-
/// <param name="value">回调方法</param>
216+
/// <param name="component">Component</param>
217+
/// <param name="value">Callback method</param>
217218
public void RegisterShownCallback(IComponent component, Func<Task> value)
218219
{
219220
_shownCallbackCache.AddOrUpdate(component, _ => value, (_, _) => value);
220221
}
221222

222223
/// <summary>
223-
/// 取消注册窗口显示后回调方法
224+
/// Unregisters the callback method to be called after the popup is shown
224225
/// </summary>
225-
/// <param name="component">组件</param>
226+
/// <param name="component">Component</param>
226227
public void UnRegisterShownCallback(IComponent component)
227228
{
228229
_shownCallbackCache.TryRemove(component, out _);

src/BootstrapBlazor/Components/Modal/ModalDialog.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
@inherits BootstrapModuleComponentBase
33
@attribute [BootstrapModuleAutoLoader("Modal/ModalDialog.razor.js", JSObjectReference = true)]
44

5-
<div class="@ClassName" id="@Id">
5+
<div @attributes="AdditionalAttributes" class="@ClassName" id="@Id">
66
<div class="modal-content">
77
@if (ShowHeader)
88
{

src/BootstrapBlazor/Components/Modal/ModalDialog.razor.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public partial class ModalDialog : IHandlerException
2727
.AddClass("is-draggable-center", IsCentered && IsDraggable && _firstRender)
2828
.AddClass("d-none", !IsShown)
2929
.AddClass(Class, !string.IsNullOrEmpty(Class))
30+
.AddClassFromAttributes(AdditionalAttributes)
3031
.Build();
3132

3233
/// <summary>

src/BootstrapBlazor/Components/SweetAlert/SweetAlert.razor

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
@inherits BootstrapComponentBase
33
@inject SwalService Swal
44

5-
<div class="swal">
6-
<Modal @ref="ModalContainer" IsKeyboard="false" OnCloseAsync="OnCloseAsync">
7-
@RenderDialog()
8-
</Modal>
9-
</div>
5+
<Modal @ref="ModalContainer" IsKeyboard="false" OnCloseAsync="OnCloseAsync" class="swal">
6+
@RenderDialog()
7+
</Modal>

src/BootstrapBlazor/Components/SweetAlert/SweetAlert.razor.cs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,18 @@
66
namespace BootstrapBlazor.Components;
77

88
/// <summary>
9-
/// SweetAlert 组件
9+
/// SweetAlert component
1010
/// </summary>
1111
public partial class SweetAlert : IAsyncDisposable
1212
{
1313
/// <summary>
14-
/// 获得/设置 Modal 容器组件实例
14+
/// Gets or sets the Modal container component instance
1515
/// </summary>
1616
[NotNull]
1717
private Modal? ModalContainer { get; set; }
1818

1919
/// <summary>
20-
/// DialogServices 服务实例
20+
/// Gets or sets the DialogServices service instance
2121
/// </summary>
2222
[Inject]
2323
[NotNull]
@@ -46,10 +46,10 @@ protected override void OnInitialized()
4646
{
4747
base.OnInitialized();
4848

49-
// 注册 Swal 弹窗事件
49+
// Register Swal popup event
5050
SwalService.Register(this, Show);
5151

52-
// 设置 OnCloseAsync 回调方法
52+
// Set OnCloseAsync callback method
5353
OnCloseAsync = () =>
5454
{
5555
IsShowDialog = false;
@@ -78,10 +78,10 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
7878

7979
if (IsShowDialog)
8080
{
81-
// 打开弹窗
81+
// Open popup
8282
await ModalContainer.Show();
8383

84-
// 自动关闭处理逻辑
84+
// Auto close handling logic
8585
if (AutoHideCheck())
8686
{
8787
try
@@ -112,7 +112,7 @@ private async Task Show(SwalOption option)
112112
{
113113
if (!IsShowDialog)
114114
{
115-
// 保证仅打开一个弹窗
115+
// Ensure only one popup is opened
116116
IsShowDialog = true;
117117

118118
IsAutoHide = option.IsAutoHide;
@@ -131,7 +131,7 @@ private async Task Show(SwalOption option)
131131

132132
OnCloseCallbackAsync = AutoHideCheck() ? option.OnCloseAsync : null;
133133

134-
// 渲染 UI 准备弹窗 Dialog
134+
// Render UI to prepare popup Dialog
135135
await InvokeAsync(StateHasChanged);
136136
}
137137
}
@@ -151,7 +151,7 @@ private RenderFragment RenderDialog() => builder =>
151151
private bool disposed;
152152

153153
/// <summary>
154-
/// Dispose 方法
154+
/// Dispose method
155155
/// </summary>
156156
/// <param name="disposing"></param>
157157
protected virtual async ValueTask DisposeAsync(bool disposing)
@@ -162,22 +162,22 @@ protected virtual async ValueTask DisposeAsync(bool disposing)
162162

163163
if (IsShowDialog)
164164
{
165-
// 关闭弹窗
165+
// Close popup
166166
DelayToken.Cancel();
167167
await ModalContainer.Close();
168168
IsShowDialog = false;
169169
}
170170

171-
// 释放 Token
171+
// Release Token
172172
DelayToken.Dispose();
173173

174-
// 注销服务
174+
// Unregister service
175175
SwalService.UnRegister(this);
176176
}
177177
}
178178

179179
/// <summary>
180-
/// Dispose 方法
180+
/// <inheritdoc/>
181181
/// </summary>
182182
public async ValueTask DisposeAsync()
183183
{

src/BootstrapBlazor/Components/SweetAlert/SweetAlert.razor.scss

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
.swal {
2-
position: fixed;
3-
--bb-swal-zindex: 1075;
4-
z-index: var(--bb-swal-zindex);
5-
}
6-
71
.swal2-header {
82
display: flex;
93
flex-direction: column;

0 commit comments

Comments
 (0)