Files
duempelkas/src/Duempelkas.App/Components/Dialogs/ModalDialog.razor
T

81 lines
2.9 KiB
Plaintext

@implements IAsyncDisposable
@inject IJSRuntime JS
<dialog @ref="element" class="dialog-content app-modal" aria-labelledby="@titleId">
<ToastHost InDialog="true" />
<h2 id="@titleId" class="visually-hidden">@Title</h2>
<div inert="@discardPrompt">@ChildContent</div>
@if (discardPrompt)
{
<section role="alertdialog" aria-label="Ungespeicherte Eingaben">
<h3>Ungespeicherte Eingaben</h3>
<p>Die Änderungen wurden noch nicht gespeichert. Möchtest du weiter bearbeiten oder die Eingaben verwerfen?</p>
<div class="dialog-actions">
<button type="button" class="btn btn-primary" data-discard-continue @onclick="ContinueEditing">Weiter bearbeiten</button>
<button type="button" class="btn btn-outline-danger" @onclick="Discard">Eingaben verwerfen</button>
</div>
</section>
}
</dialog>
@code {
[Parameter] public string Title { get; set; } = "Dialog";
[Parameter] public RenderFragment? ChildContent { get; set; }
[Parameter] public EventCallback OnCancel { get; set; }
[Parameter] public bool Dirty { get; set; }
[Parameter] public bool Busy { get; set; }
private readonly string titleId = "dialog-" + Guid.NewGuid().ToString("N");
private ElementReference element;
private DotNetObjectReference<ModalDialog>? reference;
private bool discardPrompt;
private bool focusPrompt;
private bool disposed;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
reference = DotNetObjectReference.Create(this);
await JS.InvokeVoidAsync("duempelkasDialog.open", element, reference);
}
if (focusPrompt)
{
focusPrompt = false;
await JS.InvokeVoidAsync("duempelkasDialog.focus", element, discardPrompt ? "[data-discard-continue]" : "[data-initial-focus],input,select,textarea,button");
}
}
[JSInvokable]
public async Task RequestCloseAsync()
{
if (Busy || disposed) return;
if (Dirty && !discardPrompt)
{
discardPrompt = true;
focusPrompt = true;
await InvokeAsync(StateHasChanged);
}
else if (discardPrompt)
{
await ContinueEditing();
await InvokeAsync(StateHasChanged);
}
else await OnCancel.InvokeAsync();
}
private Task ContinueEditing()
{
discardPrompt = false;
focusPrompt = true;
return Task.CompletedTask;
}
private Task Discard() => OnCancel.InvokeAsync();
public async ValueTask DisposeAsync()
{
disposed = true;
try { await JS.InvokeVoidAsync("duempelkasDialog.close", element); }
catch (Exception ex) when (ex is JSException or JSDisconnectedException or ObjectDisposedException or TaskCanceledException) { }
reference?.Dispose();
}
}