I'm trying to load a JavaScript file in a child component and expose its methods to the parent. I've been able to load the file, but any time I try to use my methods outside of the child component, I get an error. I've provided a minimum example for reference.
I'm really stuck with why this isn't working... My thought is that is has something to do with the child component not being fully rendered. And I'm not really sure how to fix it.
// Page.razor
<ChildComponent @ref="Ref" />
@code {
private ChildComponent Ref;
protected override async Task OnAfterRenderAsync()
{
await Ref.Test();
}
}
// ChildComponent.razor
@inject IJSRuntime JS
@code {
private IJSObjectReference Module;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
Module = await JS.InvokeAsync<IJSObjectReference>("import", "./ChildComponent.razor.js");
}
}
public async Task Test()
{
await Module.InvokeVoidAsync("Test");
}
}
// ChildComponent.razor.js
export function Test() {
alert("Hello world!");
}
In this component I dyamically load the '.js'.
Note: This component exists in a RCL called "ChatClient.Core". The .js file is placed within wwwroot folder wwwroot/scripts of the RCL.
public partial class Dialog : ComponentBase, IAsyncDisposable
{
private readonly Lazy<Task<IJSObjectReference>> moduleTask;
private DotNetObjectReference<Dialog> dotNetObjectReference;
private ElementReference dialogElement;
public Dialog()
{
moduleTask = new(() => jsRuntime!.InvokeAsync<IJSObjectReference>(
identifier: "import",
args: "./_content/ChatClient.Core/scripts/dialogJsInterop.js")
.AsTask());
dotNetObjectReference = DotNetObjectReference.Create(this);
}
[Inject]
private IJSRuntime jsRuntime { get; set; }
...
public async ValueTask ShowDialogAsync()
{
var module = await moduleTask.Value;
await module.InvokeVoidAsync(identifier: "showDialog", dialogElement, dotNetObjectReference);
}
...
public async ValueTask DisposeAsync()
{
if (moduleTask.IsValueCreated)
{
var module = await moduleTask.Value;
await module.DisposeAsync();
}
}
}
export function showDialog(element, parm) {
let dialog = element;
let dotNetHelper = parm;
dialog.addEventListener('close', () => {
dotNetHelper.invokeMethodAsync('OnDialogClosed');
});
return element.showModal();
}