📌
Blazor から JavaScript のクラスのコンストラクタを呼びたい
Blazor には JavaScirpt の相互運用機能があります。
.NET から JavaScript の処理を呼び出したり…
JavaScript から .NET の処理を呼び出すことが出来ます。
ということは、JavaScript じゃないと出来ないことは JavaScript に書いて C# から呼び出してしまえば何でも出来る!!ということで JavaScript で適当なクラスを定義したとしましょう。このオブジェクトを作るためにはコンストラクタを呼び出さないといけないのですが、残念ながら .NET 7 時点ではできません。これは .NET 8 で実装が予定されているためおとなしく待ちましょう…。実装されるといいな。
詳細は以下の Issue で確認できます。この Issue が .NET 8 の時点でクローズされていれば実装されたということですね!
回避方法
ということで .NET 6, .NET 7 の時点では以下のようにインスタンスを生成するための静的メソッドや関数を定義してお茶を濁す感じになります。
試してみましょう。wwwroot
に scripts.js
という名前で以下のような JavaScript ファイルを作ります。
scripts.js
export class Sample {
constructor(name) {
this.name = name;
}
alert() {
window.alert(`Hello ${this.name}`);
}
// インスタンス作るためのメソッド
static create(name) {
return new Sample(name);
}
}
そして Index.razor
あたりで以下のようなコードを書いて Sample.create
メソッドを呼んで Sample
クラスのインスタンスを作って alert
メソッドを呼び出してみます。
Index.razor
@page "/"
@inject IJSRuntime _js
@implements IAsyncDisposable
<PageTitle>Index</PageTitle>
<h1>Hello, world!</h1>
<button @onclick="OnClick">Click me</button>
@code {
private IJSObjectReference? _module;
private IJSObjectReference? _class;
private async Task OnClick()
{
if (_class is null) return;
await _class.InvokeVoidAsync("alert");
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
_module = await _js.InvokeAsync<IJSObjectReference>(
"import", "./scripts.js"
);
_class = await _module.InvokeAsync<IJSObjectReference>("Sample.create", "okazuki");
}
}
async ValueTask IAsyncDisposable.DisposeAsync()
{
if (_module is not null)
try { await _module.DisposeAsync(); } catch { }
if (_class is not null)
try { await _class.DisposeAsync(); } catch { }
}
}
実行してボタンを押すと以下のように表示されます。ちゃんと JavaScript のクラスのインスタンスを作ってメソッドを呼べてますね!!
まとめ
.NET 8 で実装されますように。
Discussion