入門者向け

【Blazor】EventCallbackで子コンポーネントからイベントを受け取る方法

blazor-event-callback
子コンポーネントからイベントを受け取るにはどうしたらいいの?

こんな疑問を解決します。

マウスをクリックしたときや何かを入力したときなど、さまざまなタイミングのイベントが用意されています。

子コンポーネントからイベントを受け取るには、EventCallback を使えば実現できます。

もし EventCallback を使えないままだと、全体的に無駄な処理が増える可能性があるので、覚えておいたほうがいいでしょう。

実装のイメージ図は次のとおりです。

blazor-event-callback

構成としてはシンプルなので、本記事を読み終える頃には使いこなせるようになっていると思います。

それでは、さっそく見ていきましょう。

EventCallbackで子コンポーネントからイベントを受け取る方法

動作確認用に EventCallbackParent.razor を新規に作成しました。

EventCallbackParent.razor
@page "/eventcallback-parent"

<h1>EventCallbackサンプル</h1>

<p>@message</p>

@code {
    private string message;
}

このファイルに、処理を追加していきます。

イベントをそのまま受け取る

まずは、子コンポーネントで発生したイベントをそのまま受け取るパターンを見てきます。

子コンポーネントを作成しましょう。

EventCallbackChild1.razor
@*イベントをそのまま返すパターン*@
<p>
    <button class="btn btn-primary" @onclick="OnClickCallback">
        ボタン1
    </button>
</p>

@code {

    [Parameter]
    public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}

ボタンを押したイベントを、親にそのまま返却しています。

イベントを返すには、Parameter 属性を付けた EventCallback を定義します。

マウス系のイベントなので、MouseEventArgs というイベント変数も返り値に含まれていますね。

これにより、子で発生したイベントが親に伝わるようになります。

次に、親のコンポーネントを修正していきましょう。

EventCallbackParent.razor
@page "/eventcallback-parent"

<h1>EventCallbackサンプル</h1>

<EventCallbackChild1 OnClickCallback="@ShowMessage1" />

<p>@message</p>

@code {
    private string message;

    private void ShowMessage1(MouseEventArgs e)
    {
        message = "ボタン1が押されました!";
    }
}

子コンポーネントのイベントを、ShowMessage1 メソッドで受け取っています。

ボタンが押されると、子コンポーネントからイベントが伝わり、画面上にメッセージが表示される仕組みができました。

実際にボタン1を押してみると、メッセージが表示されたことが確認できました。

blazor-event-callback

子で一度イベントを受け取ってから返す

イベントをそのまま返すのではなく、子コンポーネントで何かしら処理をしたあとにイベントを返したい、というケースを見ていきます。

EventCallbackChild2.razor
@*一度イベントを受け取ってから返すパターン*@
<p>
    <button class="btn btn-secondary" @onclick="OnButtonClicked">
        ボタン2
    </button>
</p>

@code {

    [Parameter]
    public EventCallback<int> OnClickCallback { get; set; }

    private async Task OnButtonClicked()
    {
        var r = new Random();
        await OnClickCallback.InvokeAsync(r.Next(0, 9));
    }

}

先ほどと違う点としては、次のとおりです。

  • コールバック関数を直接呼ばずに、一度別の関数を経由している
  • EventCallback の返り値が int になっている
  • 明示的にイベント返却の処理を書いている

返り値の数値は、0から9までをランダムに返すようにしました。

次に、親コンポーネントから呼び出す処理を書いていきましょう。

EventCallbackParent.razor
@page "/eventcallback-parent"

<h1>EventCallbackサンプル</h1>

<EventCallbackChild1 OnClickCallback="@ShowMessage1" />
<EventCallbackChild2 OnClickCallback="@ShowMessage2" />

<p>@message</p>

@code {
    private string message;

    private void ShowMessage1(MouseEventArgs e)
    {
        message = "ボタン1が押されました!";
    }

    private void ShowMessage2(int num)
    {
        message = $"ボタン2が押されました! 返り値:{num}";
    }
}

引数が変わっている以外は、特に変わった点はありませんね。

動作確認をしてみると、押すたびに数値が変わることが確認できました。

blazor-event-callback
blazor-event-callback

イベント処理をラムダ式で書く

イベントが多くなると、その分メソッドの数も増えていきます。

処理が1行で終わるようなシンプルなものについては、ラムダ式を使うことで記述量を減らすこともできます。

新たに子コンポーネントを作成しましょう。

EventCallbackChild3.razor
@*イベント処理をラムダ式で書くパターン*@
<p>
    <button class="btn btn-success" @onclick=@(async () => await OnClickCallback.InvokeAsync(10))>
        ボタン3
    </button>
</p>

@code {

    [Parameter]
    public EventCallback<int> OnClickCallback { get; set; }
}

数値の10を固定で返すプログラムですが、メソッドは定義していません。

少しスッキリした感じになりましたね。

親の方も、ラムダ式で受け取ることができます。

EventCallbackParent.razor
@page "/eventcallback-parent"

<h1>EventCallbackサンプル</h1>

<EventCallbackChild1 OnClickCallback="@ShowMessage1" />
<EventCallbackChild2 OnClickCallback="@ShowMessage2" />
<EventCallbackChild3 OnClickCallback=@((num) => message = $"ボタン3が押されました! 返り値:{num}") />

<p>@message</p>

@code {
    private string message;

    private void ShowMessage1(MouseEventArgs e)
    {
        message = "ボタン1が押されました!";
    }

    private void ShowMessage2(int num)
    {
        message = $"ボタン2が押されました! 返り値:{num}";
    }
}

動作確認をしてみると、特に問題なく動作することが確認できました。

blazor-event-callback

最後に

EventCallbackで子コンポーネントからイベントを受け取る方法について見てきました。

「イベントを返す」という点では Blazor 特有の考え方もなく、理解しやすかったのではないでしょうか。

コンポーネントの部品化をしながら、イベントの実装もしてみてください。

Blazor の書籍も好評発売中!
blazor-book

入門編から EC サイトを作る応用編まで、Blazor の本を3冊執筆しました。

私が1年以上かけて学習した内容をすべて詰め込んでいるので、さらにステップアップしたい方はぜひご覧ください。