Aggiunto componente Bootstrap modale

This commit is contained in:
Samuele Locatelli
2026-05-05 10:34:12 +02:00
parent 7433f6a676
commit aa2719c9eb
11 changed files with 186 additions and 128 deletions
@@ -0,0 +1,111 @@
@inject IJSRuntime JS
<div class="modal fade" id="@ModalId" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-top">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">@Title</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"
@onclick="OnCancel"></button>
</div>
<div class="modal-body">
<p>@Message</p>
@if (Mode == ModalMode.Prompt)
{
<input @bind="UserInput" class="form-control" placeholder="@Placeholder" />
}
</div>
<div class="modal-footer">
@if (Mode == ModalMode.Message)
{
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" @onclick="OnOk">OK</button>
}
else if (Mode == ModalMode.Confirm)
{
<button type="button" class="btn btn-primary" @onclick="OnConfirm">Yes</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" @onclick="OnCancel">No</button>
}
else if (Mode == ModalMode.Prompt)
{
<button type="button" class="btn btn-primary" @onclick="OnPromptOk">OK</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" @onclick="OnCancel">Cancel</button>
}
</div>
</div>
</div>
</div>
@code {
private TaskCompletionSource<object?>? tcs;
private string ModalId { get; } = $"modal_{Guid.NewGuid():N}";
[Parameter]
public string Title { get; set; } = "Modal";
[Parameter]
public string Message { get; set; } = "";
[Parameter]
public string UserInput { get; set; } = "";
[Parameter]
public string Placeholder { get; set; } = "";
[Parameter]
public ModalMode Mode { get; set; } = ModalMode.Message;
/// <summary>
/// Mostra la modale ed aspetta risultato utente
/// </summary>
public async Task<T?> ShowAsync<T>()
{
tcs = new TaskCompletionSource<object?>();
await JS.InvokeVoidAsync("bootstrapModalHelper.show", $"#{ModalId}");
var result = await tcs.Task;
// Convert result to requested type
if (result is null)
return default;
return (T)result;
}
private async Task OnOk()
{
await JS.InvokeVoidAsync("bootstrapModalHelper.hide", $"#{ModalId}");
tcs?.TrySetResult(true);
}
private async Task OnConfirm()
{
await JS.InvokeVoidAsync("bootstrapModalHelper.hide", $"#{ModalId}");
tcs?.TrySetResult(true);
}
private async Task OnPromptOk()
{
await JS.InvokeVoidAsync("bootstrapModalHelper.hide", $"#{ModalId}");
tcs?.TrySetResult(UserInput);
}
private async Task OnCancel()
{
await JS.InvokeVoidAsync("bootstrapModalHelper.hide", $"#{ModalId}");
if (Mode == ModalMode.Prompt)
tcs?.TrySetResult(null);
else if (Mode == ModalMode.Confirm)
tcs?.TrySetResult(false);
else
tcs?.TrySetResult(null);
}
/// <summary>
/// Modalità display componente
/// </summary>
public enum ModalMode
{
Message,
Confirm,
Prompt
}
}
@@ -0,0 +1,3 @@
.modal-dialog-top {
margin-top: 1rem;
}
@@ -0,0 +1,3 @@
.modal-dialog-top {
margin-top: 1rem;
}
@@ -0,0 +1 @@
.modal-dialog-top{margin-top:1rem;}
+50 -1
View File
@@ -2,15 +2,26 @@
<h3>Pure Blazor Prompt Test</h3>
<hr />
<button class="btn btn-primary" @onclick="AskName">Ask Name</button>
<p>@resultMessage</p>
<CustomDialog @ref="promptDialog" Title="Test Custom Dialog" Message="Nome?" UserInput="MarioRossi" />
<i class="fa-solid fa-spinner fa-3x fa-spin"></i>
<hr />
<button class="btn btn-primary" @onclick="ShowMessage">Show Message</button>
<button class="btn btn-warning" @onclick="ShowConfirm">Show Confirm</button>
<button class="btn btn-success" @onclick="ShowPrompt">Show Prompt</button>
<hr />
<p>@resultMessage</p>
<BootstrapModal @ref="modal" Title="@cTitle" Message="@cMessage" Mode="@cMode" Placeholder="@cPlaceholder" UserInput="@cUserInput" />
@code {
private BootstrapModal? modal;
private CustomDialog? promptDialog;
private string resultMessage = "";
@@ -20,4 +31,42 @@
// var name = await promptDialog!.ShowAsync("Come ti chiami?", "(Super) Mario Rossi");
resultMessage = name is null ? "User cancelled." : $"Hello, {name}!";
}
private string cTitle = "";
private string cMessage = "";
private string cPlaceholder = "";
private string cUserInput = "";
private BootstrapModal.ModalMode cMode = BootstrapModal.ModalMode.Message;
private async Task ShowMessage()
{
cTitle = "Information";
cMessage = "This is a standard message.";
cMode = BootstrapModal.ModalMode.Message;
await modal!.ShowAsync<bool>();
resultMessage = "Message closed.";
}
private async Task ShowConfirm()
{
cTitle = "Confirm Action";
cMessage = "Are you sure you want to continue?";
cMode = BootstrapModal.ModalMode.Confirm;
bool confirmed = await modal!.ShowAsync<bool>();
resultMessage = confirmed ? "User confirmed." : "User cancelled.";
}
private async Task ShowPrompt()
{
cTitle = "Enter Name";
cMessage = "What is your name?";
cPlaceholder = "Type your name...";
cUserInput = "";
cMode = BootstrapModal.ModalMode.Prompt;
string? name = await modal!.ShowAsync<string?>();
resultMessage = name is null ? "User cancelled." : $"Hello, {name}!";
}
}
@@ -18,5 +18,9 @@
{
"outputFile": "Pages/TestBarcodeReader.razor.css",
"inputFile": "Pages/TestBarcodeReader.razor.less"
},
{
"outputFile": "Pages/BootstrapModal.razor.css",
"inputFile": "Pages/BootstrapModal.razor.less"
}
]
+14 -14
View File
@@ -33,20 +33,6 @@
[Parameter]
public string UserInput { get; set; } = "";
/// <summary>
/// Shows the Bootstrap modal and waits for user input.
/// </summary>
public async Task<string?> ShowAsync(string message, string defaultValue = "", string title = "Prompt")
{
Title = title;
Message = message;
UserInput = defaultValue;
tcs = new TaskCompletionSource<string?>();
await JS.InvokeVoidAsync("bootstrapModalHelper.show", $"#{ModalId}");
return await tcs.Task;
}
/// <summary>
/// Shows the Bootstrap modal and waits for user input.
/// </summary>
@@ -60,6 +46,20 @@
await JS.InvokeVoidAsync("bootstrapModalHelper.show", $"#{ModalId}");
return await tcs.Task;
}
/// <summary>
/// Shows the Bootstrap modal and waits for user input.
/// </summary>
public async Task<string?> ShowAsync(string message, string defaultValue = "", string title = "Prompt")
{
Title = title;
Message = message;
UserInput = defaultValue;
tcs = new TaskCompletionSource<string?>();
await JS.InvokeVoidAsync("bootstrapModalHelper.show", $"#{ModalId}");
return await tcs.Task;
}
private async Task Confirm()
{
-46
View File
@@ -1,46 +0,0 @@
<div class="modal-overlay" style="@(_isVisible ? "display:flex;" : "display:none;")">
<div class="modal-box align-items-top">
<p>@Message</p>
<input @bind="UserInput" placeholder="Type here..." />
<div class="modal-buttons">
<button class="btn btn-sm btn-success" @onclick="Confirm">OK</button>
<button class="btn btn-sm btn-warning" @onclick="Cancel">Cancel</button>
</div>
</div>
</div>
@code {
private bool _isVisible;
private TaskCompletionSource<string?>? _tcs;
public string Message { get; set; } = "";
public string UserInput { get; set; } = "";
/// <summary>
/// Shows the prompt and waits for user input.
/// </summary>
public Task<string?> ShowAsync(string message, string defaultValue = "")
{
Message = message;
UserInput = defaultValue;
_isVisible = true;
StateHasChanged();
_tcs = new TaskCompletionSource<string?>();
return _tcs.Task;
}
private void Confirm()
{
_isVisible = false;
_tcs?.TrySetResult(UserInput);
}
private void Cancel()
{
_isVisible = false;
_tcs?.TrySetResult(null);
}
}
@@ -1,32 +0,0 @@
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: none;
/* Controlled by inline style in Razor */
align-items: center;
justify-content: center;
z-index: 1000;
}
.modal-box {
background: white;
padding: 20px;
border-radius: 8px;
min-width: 300px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
}
.modal-buttons {
margin-top: 15px;
display: flex;
justify-content: flex-end;
gap: 10px;
}
.modal-box input {
width: 100%;
padding: 6px;
margin-top: 10px;
box-sizing: border-box;
}
@@ -1,34 +0,0 @@
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: none; /* Controlled by inline style in Razor */
align-items: center;
justify-content: center;
z-index: 1000;
}
.modal-box {
background: white;
padding: 20px;
border-radius: 8px;
min-width: 300px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
}
.modal-buttons {
margin-top: 15px;
display: flex;
justify-content: flex-end;
gap: 10px;
}
.modal-box input {
width: 100%;
padding: 6px;
margin-top: 10px;
box-sizing: border-box;
}
-1
View File
@@ -1 +0,0 @@
.modal-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.5);display:none;align-items:center;justify-content:center;z-index:1000;}.modal-box{background:#fff;padding:20px;border-radius:8px;min-width:300px;box-shadow:0 2px 10px rgba(0,0,0,.3);}.modal-buttons{margin-top:15px;display:flex;justify-content:flex-end;gap:10px;}.modal-box input{width:100%;padding:6px;margin-top:10px;box-sizing:border-box;}