Files
aliasvault/apps/server/AliasVault.Client/Main/Components/Layout/ClickOutsideHandler.razor
2025-04-30 19:03:18 +02:00

80 lines
2.0 KiB
Plaintext

@inject IJSRuntime JSRuntime
@implements IAsyncDisposable
@ChildContent
@code {
/// <summary>
/// Callback when clicked outside the child.
/// </summary>
[Parameter]
public EventCallback<bool> OnClose { get; set; }
/// <summary>
/// The content id of the modal which is used to identity if a click is inside or outside the modal.
/// </summary>
[Parameter]
public string ContentId { get; set; } = "modal-content";
/// <summary>
/// The child content of the component.
/// </summary>
[Parameter]
public required RenderFragment ChildContent { get; set; }
private DotNetObjectReference<ClickOutsideHandler>? ObjRef { get; set; }
private IJSObjectReference? Module { get; set; }
/// <inheritdoc />
protected override async Task OnInitializedAsync()
{
await LoadModuleAsync();
}
/// <inheritdoc />
protected override async Task OnParametersSetAsync()
{
await LoadModuleAsync();
if (Module != null)
{
await Module.InvokeVoidAsync("registerClickOutsideHandler", ObjRef, ContentId, nameof(CloseHandler));
}
}
/// <summary>
/// Call close handler on parent component.
/// </summary>
[JSInvokable]
public async Task CloseHandler()
{
await OnClose.InvokeAsync();
StateHasChanged();
}
/// <inheritdoc />
public async ValueTask DisposeAsync()
{
if (Module is not null)
{
await Module.InvokeVoidAsync("unregisterClickOutsideHandler");
await Module.DisposeAsync();
}
ObjRef?.Dispose();
}
/// <summary>
/// Load the JavaScript module.
/// </summary>
private async Task LoadModuleAsync()
{
if (Module is null)
{
Module = await JSRuntime.InvokeAsync<IJSObjectReference>("import", "./js/modules/clickOutsideHandler.js");
ObjRef = DotNetObjectReference.Create(this);
}
}
}