Came up with a solution to avoid static method. In code part we need to hold reference of DotNetObjectReference
and also some index of it (that will play part in JS), this is example class:
public abstract class VideoPlayerBase : ComponentBase, IDisposable
{
[Parameter] public string Source { get; set; }
[Parameter] public EventCallback VideoEndedCallback { get; set; }
[Inject] protected IJSRuntime JS { get; set; }
/// <summary>
/// DotNetObjectReference of current component instance.
/// This is used for catching `onended` event on video tag (which apparently is not supported by Blazor)
/// </summary>
private DotNetObjectReference<VideoPlayerBase>? _dotNetObjectReference;
/// <summary>
/// Index of DotNetObjectReference inside BlazorApp.dotNetObjectReferences array.
/// This is used to be able to relevant DotNetObjectReference from PriskApp.dotNetObjectReferences array.
/// </summary>
protected int DotNetObjectReferenceIndex { get; set; } = -1;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
_dotNetObjectReference = DotNetObjectReference.Create(this);
DotNetObjectReferenceIndex = await JS.InvokeAsync<int>("BlazorApp.addDotNetObjectReference", _dotNetObjectReference);
}
[JSInvokable("VideoEnded")]
public async Task VideoEndedAsync()
{
await VideoEndedCallback.InvokeAsync(null);
}
public void Dispose()
{
_dotNetObjectReference?.Dispose();
}
}
Then we need js part:
var BlazorApp = BlazorApp || {
dotNetObjectReferences: [],
addDotNetObjectReference: function (dotNetObjectReference) {
PriskApp.dotNetObjectReferences.push(dotNetObjectReference);
return PriskApp.dotNetObjectReferences.length - 1;
},
getDotNetObjectReference: function (index) {
return PriskApp.dotNetObjectReferences[index];
},
};
And lastly the component view:
@inherits VideoPlayerBase
<div>
<video style="width:100%;" controls onended="(BlazorApp.getDotNetObjectReference(@DotNetObjectReferenceIndex).invokeMethodAsync('VideoEnded'))()">
<source src="@Source" type="video/mp4" controls>
Your browser does not support HTML video.
</video>
</div>
So basically this work by creating DotNetObjectReference
in OnInitializedAsync
method and then calling js function BlazorApp.addDotNetObjectReference
to add this reference to some js array and to get index of it, which is used in view part. Then once Video ends onended event is triggered and inside it it gets the relevant DotNetObjectReference
and calls its method.