更新:我将这个答案转化成了一个服务,可以在这里找到。
我修改了Kyles和grammophones的答案,以支持我们所喜爱的Alert
、Prompt
和Confirm
,同时支持C#和JavaScript。在最新的Blazor Server版本中使用Bootstrap 5进行测试。
ProjectName.Components.Modal.razor
@using Microsoft.JSInterop
<div class="modal @ModalClass" tabindex="-1" role="dialog" style="display:@ModalDisplay; overflow-y: auto;">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title w-100 text-center" style="padding-left:31px">@Title</h5>
<button type="button" class="close border-0 bg-white" data-dismiss="modal" aria-label="Close" @onclick="() => Close(true)">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body mx-auto text-center">
@Body
@if (MType == ModalType.Prompt){
<input type="text" class="form-control text-center my-2" @bind-value="PromptValue" style="max-width:400px"></input>
}
</div>
<div class="modal-footer justify-content-center">
@if (MType == ModalType.Prompt || MType == ModalType.Confirm)
{
<button type="button" class="btn btn-secondary" data-dismiss="modal" @onclick="() => Close(false)">OK</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal" @onclick="() => Close(true)">Cancel</button>
}
else
{
<button type="button" class="btn btn-secondary" data-dismiss="modal" @onclick="() => Close(false)">Close</button>
}
</div>
</div>
</div>
</div>
@if (ShowBackdrop)
{
<div class="modal-backdrop fade show"></div>
}
@code {
[Inject] IJSRuntime JS { get; set; }
public enum ModalType
{
Alert,
Prompt,
Confirm
}
protected override async Task OnInitializedAsync()
{
JS.InvokeVoidAsync("MODAL.SetDotnetReference", DotNetObjectReference.Create(this));
}
private string Title { get; set; }
private string Body { get; set; }
public Guid Guid = Guid.NewGuid();
public string ModalDisplay = "none;";
public string ModalClass = "";
public bool ShowBackdrop = false;
private string PromptValue { get; set; }
private bool ConfirmValue { get; set; }
private ModalType MType { get; set; }
private List<string> MsgIds = new List<string>();
[JSInvokable("Show")]
public async Task<dynamic> Show(ModalType mType, string title, string body)
{
string msgId = Guid.NewGuid().ToString();
if (!MsgIds.Contains(msgId))
MsgIds.Add(msgId);
while (MsgIds.Count > 1 && MsgIds.IndexOf(msgId) != 0)
await Task.Delay(250);
Title = title;
Body = body;
ModalDisplay = "block;";
ModalClass = "Show";
MType = mType;
ShowBackdrop = true;
StateHasChanged();
while (ShowBackdrop)
await Task.Delay(250);
switch(mType)
{
default:
case ModalType.Alert:
MsgIds.Remove(msgId);
return string.Empty;
case ModalType.Confirm:
bool confirmResponse = ConfirmValue;
MsgIds.Remove(msgId);
return confirmResponse;
case ModalType.Prompt:
string promptResponse = PromptValue;
MsgIds.Remove(msgId);
return promptResponse;
}
}
private void Close(bool isCancel)
{
PromptValue = isCancel ? string.Empty : PromptValue;
ConfirmValue = isCancel ? false : true;
ModalDisplay = "none";
ModalClass = "";
ShowBackdrop = false;
StateHasChanged();
}
}
标记用法
<Modal @ref="Modal"></Modal>
<button @onclick='() => Modal.Show(Modal.ModalType.Alert, "Title goes here","Body goes here")'>Open Modal</button>
代码使用
if (await Modal.Show(Modal.ModalType.Confirm,"Save Settings", "Are you sure you want to save settings?"))
{
string fileName = await Modal.Show(Modal.ModalType.Prompt, "File Name", "Please enter a filename");
if (!string.IsNullOrEmpty(fileName))
await Modal.Show(Modal.ModalType.Alert, "File Saved", $"File Saved as {fileName}");
}
JavaScript使用
通过支持Promise,我们可以直接从JavaScript中获取Prompt
和Confirm
的响应。为了避免将我们的Modal
声明为静态,我们需要设置一个DotNetReference
。
var MODAL = {};
MODAL.DotNetReference = null;
MODAL.SetDotnetReference = function (pDotNetReference) {
MODAL.DotNetReference = pDotNetReference;
};
MODAL.MType = {
Alert: 0,
Prompt:1,
Confirm: 2,
};
MODAL.DotNetReference.invokeMethodAsync('Show', MODAL.MType.Prompt, `Title goes here`, `Body goes here`)
.then(data => {
console.log(`Prompt Response`, data);
});
JavaScript 注意:建议在旧版浏览器中使用Polyfil以支持Promise