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