如何使用 Blazor 使用 alert()、confirm() 和 prompt() 函数?
How to use alert(),confirm() and prompt() function using Blazor?
我正在学习 Blazor 技术。我在 VS 2019 中启动了一个默认的增量项目,我已经用 confirm() 和 alert 修改了 Decrement 的代码,但它不起作用。
@page "/counter"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Increment</button>
<button class="btn btn-primary btn-danger" onclick="if (confirm('Are you sure to Decrement')) { @DecrementCount() }">Decrement</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
private void DecrementCount()
{
currentCount--;
// alert('Operation Successfully executed')
}
}
在我的代码片段中,confirm() 函数运行良好,但我想调用一个 Decrement 函数不工作,构建失败。
我想在我的函数中添加一条成功消息。
请提供任何选项,而不是使用 confirm(),alert() 函数。
不幸的是,Blazor 还没有实现这些有用的功能。
所以你需要使用 JSRuntime
实例。
@inject IJSRuntime JsRuntime
...
@code
{
//...
await JsRuntime.InvokeVoidAsync("alert", "Warning!"); // Alert
bool confirmed = await JsRuntime.InvokeAsync<bool>("confirm", "Are you sure?"); // Confirm
string prompted = await JsRuntime.InvokeAsync<string>("prompt", "Take some input:"); // Prompt
//...
}
它使在 C# 代码中执行 JS 代码成为可能。有了它,您可以使用任何您想要的 JS 逻辑来创建您需要的行为。
详情见docs。
我是 Blazor 的新手,是 JavaScript Alert、Confirm 和 Prompt 的替代品 是我名单上的第一件事。我在 Blazor Server / BlazorWebView 中想出了一个服务(我还没有在 Web Assembly 中测试过)。我们将创建的 <Modal>
组件可以由服务控制或直接从 JavaScript 控制。虽然,如果您不需要通过 JavaScript 调用 <Modal>
,那么您可以删除任何 JavaScript 或 IJSRuntime
引用。
ModalService.cs
很简单。它有一个 OnShow
事件,我们可以稍后将其挂接到我们的 <Modal>
组件中。该事件是一个接受参数 ModalType、title、body 和 returns 的函数动态任务.
设置
ModalService.cs
namespace MyProjectName.Services
{
public class ModalService
{
public event Func<ModalBase.ModalType, string, string,Task<dynamic>> OnShow;
public async Task<dynamic> Show(ModalBase.ModalType mType, string title, string body)
{
if(OnShow != null)
return await OnShow?.Invoke(mType, title, body);
return null;
}
}
}
ModalBase.cs
将被我们的 <Modal>
组件继承。它处理打开和关闭模式。在这里我们还可以附加到 ModalService
事件 OnShow
并连接对 JavaScript 调用的支持。
ModalBase.cs
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
namespace MyProjectName.Services
{
public class ModalBase : ComponentBase, IDisposable
{
[Inject] ModalService ModalService { get; set; }
[Inject] IJSRuntime JS { get; set; }
public enum ModalType
{
Alert,
Prompt,
Confirm
}
protected override void OnInitialized()
{
// Attach to our service event.
ModalService.OnShow += Show;
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
// Set a JavaScript referene for our DotNet interop.
if(firstRender)
await JS.InvokeVoidAsync("MODAL.SetDotnetReference", DotNetObjectReference.Create(this));
}
public string Title { get; set; }
public string Body { get; set; }
public Guid Guid = Guid.NewGuid();
public string ModalDisplay = "none;";
public string ModalClass = "";
public bool ShowBackdrop = false;
public string PromptValue { get; set; }
private bool ConfirmValue { get; set; }
public ModalType MType { get; set; }
private List<string> MsgIds = new List<string>();
[JSInvokable("Show")]
public async Task<dynamic> Show(ModalType mType, string title, string body)
{
// The JavaScript call MODAL.DotNetReference.invokeMethodAsync is non-blocking
// This means multiple calls to show the modal using invokeMethodAsync will only show the modal once.
// We can solve this by making sure each message waits in line.
string msgId = Guid.NewGuid().ToString();
if (!MsgIds.Contains(msgId))
MsgIds.Add(msgId);
// If multiple messages are being processed, wait for this msgs turn.
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;
}
}
public void Close(bool isCancel)
{
// Determine returned values.
PromptValue = isCancel ? string.Empty : PromptValue;
ConfirmValue = isCancel ? false : true;
ModalDisplay = "none";
ModalClass = "";
ShowBackdrop = false;
StateHasChanged();
}
public void Dispose()
{
ModalService.OnShow -= Show;
}
}
}
我根据 讨论的 bootstrap 标记设计了 <Modal>
组件。主要区别在于我已经将胆量转移到 ModalBase.cs
以与我们的服务进行交互。
Modal.razor
@using Microsoft.JSInterop
@using MyProjectName.Services
@inherits ModalBase
<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 text-break">
@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>
}
用法
将 ModalService
纳入我们的服务集合。
Program.cs
builder.Services.AddScoped<ModalService>();
MainLayout.razor
@using MyProjectName.Components
@inherits LayoutComponentBase
<PageTitle>My Project</PageTitle>
<Modal></Modal>
<div class="page">
.
.
.
</div>
在您的应用程序中的某处注入并使用该服务。
Index.razor
@code
{
[Inject] public ModalService ModalService { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
if (await ModalService.Show(Modal.ModalType.Confirm,"Save Settings", "Are you sure you want to save settings?"))
{
string fileName = await ModalService.Show(Modal.ModalType.Prompt, "File Name", "Please enter a filename");
if (!string.IsNullOrEmpty(fileName))
await ModalService.Show(Modal.ModalType.Alert, "File Saved Success", $"File Saved as {fileName}");
else
await ModalService.Show(Modal.ModalType.Alert, "File Saved Cancelled", $"No file name was entered.");
}
}
// return base.OnAfterRenderAsync(firstRender);
}
}
JavaScript 用法
// Defined somewhere globally
var MODAL = {};
MODAL.DotNetReference = null;
MODAL.SetDotnetReference = function (pDotNetReference) {
MODAL.DotNetReference = pDotNetReference;
};
MODAL.MType = {
Alert: 0,
Prompt:1,
Confirm: 2,
};
// Called from wherever
MODAL.DotNetReference.invokeMethodAsync('Show', MODAL.MType.Prompt, `Title goes here`, `Body goes here`)
.then(data => {
console.log(`Prompt Response`, data);
});
JavaScript 注意:建议使用 Polyfil 以在旧版浏览器中提供 promise 支持
注意: 如果您需要在应用程序生命周期的早期阶段显示模式,例如 OnInitializedAsync
,那么您需要更改 ServerPrerendered
到 Server
.
@*<component type="typeof(App)" render-mode="ServerPrerendered" />*@
<component type="typeof(App)" render-mode="Server" />
我正在学习 Blazor 技术。我在 VS 2019 中启动了一个默认的增量项目,我已经用 confirm() 和 alert 修改了 Decrement 的代码,但它不起作用。
@page "/counter"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Increment</button>
<button class="btn btn-primary btn-danger" onclick="if (confirm('Are you sure to Decrement')) { @DecrementCount() }">Decrement</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
private void DecrementCount()
{
currentCount--;
// alert('Operation Successfully executed')
}
}
在我的代码片段中,confirm() 函数运行良好,但我想调用一个 Decrement 函数不工作,构建失败。 我想在我的函数中添加一条成功消息。 请提供任何选项,而不是使用 confirm(),alert() 函数。
不幸的是,Blazor 还没有实现这些有用的功能。
所以你需要使用 JSRuntime
实例。
@inject IJSRuntime JsRuntime
...
@code
{
//...
await JsRuntime.InvokeVoidAsync("alert", "Warning!"); // Alert
bool confirmed = await JsRuntime.InvokeAsync<bool>("confirm", "Are you sure?"); // Confirm
string prompted = await JsRuntime.InvokeAsync<string>("prompt", "Take some input:"); // Prompt
//...
}
它使在 C# 代码中执行 JS 代码成为可能。有了它,您可以使用任何您想要的 JS 逻辑来创建您需要的行为。
详情见docs。
我是 Blazor 的新手,是 JavaScript Alert、Confirm 和 Prompt 的替代品 是我名单上的第一件事。我在 Blazor Server / BlazorWebView 中想出了一个服务(我还没有在 Web Assembly 中测试过)。我们将创建的 <Modal>
组件可以由服务控制或直接从 JavaScript 控制。虽然,如果您不需要通过 JavaScript 调用 <Modal>
,那么您可以删除任何 JavaScript 或 IJSRuntime
引用。
ModalService.cs
很简单。它有一个 OnShow
事件,我们可以稍后将其挂接到我们的 <Modal>
组件中。该事件是一个接受参数 ModalType、title、body 和 returns 的函数动态任务.
设置
ModalService.cs
namespace MyProjectName.Services
{
public class ModalService
{
public event Func<ModalBase.ModalType, string, string,Task<dynamic>> OnShow;
public async Task<dynamic> Show(ModalBase.ModalType mType, string title, string body)
{
if(OnShow != null)
return await OnShow?.Invoke(mType, title, body);
return null;
}
}
}
ModalBase.cs
将被我们的 <Modal>
组件继承。它处理打开和关闭模式。在这里我们还可以附加到 ModalService
事件 OnShow
并连接对 JavaScript 调用的支持。
ModalBase.cs
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
namespace MyProjectName.Services
{
public class ModalBase : ComponentBase, IDisposable
{
[Inject] ModalService ModalService { get; set; }
[Inject] IJSRuntime JS { get; set; }
public enum ModalType
{
Alert,
Prompt,
Confirm
}
protected override void OnInitialized()
{
// Attach to our service event.
ModalService.OnShow += Show;
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
// Set a JavaScript referene for our DotNet interop.
if(firstRender)
await JS.InvokeVoidAsync("MODAL.SetDotnetReference", DotNetObjectReference.Create(this));
}
public string Title { get; set; }
public string Body { get; set; }
public Guid Guid = Guid.NewGuid();
public string ModalDisplay = "none;";
public string ModalClass = "";
public bool ShowBackdrop = false;
public string PromptValue { get; set; }
private bool ConfirmValue { get; set; }
public ModalType MType { get; set; }
private List<string> MsgIds = new List<string>();
[JSInvokable("Show")]
public async Task<dynamic> Show(ModalType mType, string title, string body)
{
// The JavaScript call MODAL.DotNetReference.invokeMethodAsync is non-blocking
// This means multiple calls to show the modal using invokeMethodAsync will only show the modal once.
// We can solve this by making sure each message waits in line.
string msgId = Guid.NewGuid().ToString();
if (!MsgIds.Contains(msgId))
MsgIds.Add(msgId);
// If multiple messages are being processed, wait for this msgs turn.
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;
}
}
public void Close(bool isCancel)
{
// Determine returned values.
PromptValue = isCancel ? string.Empty : PromptValue;
ConfirmValue = isCancel ? false : true;
ModalDisplay = "none";
ModalClass = "";
ShowBackdrop = false;
StateHasChanged();
}
public void Dispose()
{
ModalService.OnShow -= Show;
}
}
}
我根据 <Modal>
组件。主要区别在于我已经将胆量转移到 ModalBase.cs
以与我们的服务进行交互。
Modal.razor
@using Microsoft.JSInterop
@using MyProjectName.Services
@inherits ModalBase
<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 text-break">
@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>
}
用法
将 ModalService
纳入我们的服务集合。
Program.cs
builder.Services.AddScoped<ModalService>();
MainLayout.razor
@using MyProjectName.Components
@inherits LayoutComponentBase
<PageTitle>My Project</PageTitle>
<Modal></Modal>
<div class="page">
.
.
.
</div>
在您的应用程序中的某处注入并使用该服务。
Index.razor
@code
{
[Inject] public ModalService ModalService { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
if (await ModalService.Show(Modal.ModalType.Confirm,"Save Settings", "Are you sure you want to save settings?"))
{
string fileName = await ModalService.Show(Modal.ModalType.Prompt, "File Name", "Please enter a filename");
if (!string.IsNullOrEmpty(fileName))
await ModalService.Show(Modal.ModalType.Alert, "File Saved Success", $"File Saved as {fileName}");
else
await ModalService.Show(Modal.ModalType.Alert, "File Saved Cancelled", $"No file name was entered.");
}
}
// return base.OnAfterRenderAsync(firstRender);
}
}
JavaScript 用法
// Defined somewhere globally
var MODAL = {};
MODAL.DotNetReference = null;
MODAL.SetDotnetReference = function (pDotNetReference) {
MODAL.DotNetReference = pDotNetReference;
};
MODAL.MType = {
Alert: 0,
Prompt:1,
Confirm: 2,
};
// Called from wherever
MODAL.DotNetReference.invokeMethodAsync('Show', MODAL.MType.Prompt, `Title goes here`, `Body goes here`)
.then(data => {
console.log(`Prompt Response`, data);
});
JavaScript 注意:建议使用 Polyfil 以在旧版浏览器中提供 promise 支持
注意: 如果您需要在应用程序生命周期的早期阶段显示模式,例如 OnInitializedAsync
,那么您需要更改 ServerPrerendered
到 Server
.
@*<component type="typeof(App)" render-mode="ServerPrerendered" />*@
<component type="typeof(App)" render-mode="Server" />