これまでのレクチャーで、Home画面のエリア入力欄に文字を入力すると、画面下のパラメータ表示にリアルタイムで反映されるようになりました。しかし、その入力タイミングを「プログラム側のイベント」として拾う仕組みはまだ用意していません。今回は、入力されたタイミングをプログラム側でイベントとして検知する方法を解説します。
図1 実行画面。エリア欄に入力するとリアルタイムに下の表示へ反映される
図2 現在のHome.razorのコード。@bindでの双方向データバインドに加え、@bind:event=”oninput”でリアルタイム反映を行っている(D02・D03で作成)
AreaChangedメソッドを追加してブレークポイントを置く
まず、入力があったときに呼び出すためのメソッドとして、@codeブロックに AreaChanged() を追加し、その中にブレークポイントを置いておきます。
図3 @codeブロックにAreaChanged()メソッドを追加し、ブレークポイントを設置
@onchangeを追加するとコンパイルエラーになる
Blazorで一般的な変更通知のイベントは @onchange ですので、input要素に @onchange=”AreaChanged” を追加してみます。
<input type="text"
@bind="_areaName"
@bind:event="oninput"
@onchange="AreaChanged"
placeholder="エリアを入力してください"
style="width:300px"
class="form-control" />
図4 @onchange=”AreaChanged”を追加した状態
この状態では見た目上コンパイルエラーは出ていませんが、実際にビルドしようとすると次のエラーが表示されます。
図5 RZ10008:属性’onchange’がこの要素に対して2回以上使用されている、というエラー
これは、@bind ディレクティブ属性がすでに内部で onchange イベントを使っているためです。@bind にカーソルを合わせると、次のように説明が表示されます。「指定した式をvalue属性にバインドし、変更イベントデリゲートをonchange属性にバインドします」。つまり @bind を使っている時点で onchange はすでに1回使われており、そこへさらに @onchange を書くと、同じ属性を2回定義していることになってしまうのです。
図6 @bindのIntelliSense説明。value属性と、変更イベント(onchange)へのバインドを行うことがわかる
@bind:afterで変更後の処理を拾う
そこで @onchange の代わりに @bind:after を使います。.NET 7より前のバージョンでは、プロパティ経由で値の変更を拾うなど少し面倒な実装が必要でしたが、.NET 7以降はこの @bind:after が使えるようになり、扱いやすくなりました。@onchange を削除し、代わりに @bind:after=”AreaChanged” と書きます。
図7 @bind:after= と入力すると、IntelliSenseの候補にAreaChangedメソッドが表示される
<input type="text"
@bind="_areaName"
@bind:after="AreaChanged"
placeholder="エリアを入力してください"
style="width:300px"
class="form-control" />
図8 @bind:after=”AreaChanged”に書き換えた状態。コンパイルエラーは解消される
実行して動作を確認する
この状態で実行してみます。エリア欄に文字を入力しただけでは、まだブレークポイントに止まりません。
図9 ”1111111″と入力してもブレークポイントに来ておらず、パラメータもまだ送信されていない
入力欄からフォーカスを外す(ロストフォーカスする)と、そのタイミングでブレークポイントに到達します。これは @bind の既定の変更イベントが onchange(フォーカスが外れたときに発生)であるためです。
図10 ロストフォーカスすると、AreaChanged()内のブレークポイントで停止する
入力のたびにリアルタイムで通知させる
ロストフォーカスを待たずに、1文字入力するたびに通知を受け取りたい場合は、これまでのリアルタイム表示と同じように @bind:event=”oninput” を追加します。これにより、@bind:after で指定したメソッドが oninput のタイミングで呼ばれるようになります。
<input type="text"
@bind="_areaName"
@bind:event="oninput"
@bind:after="AreaChanged"
placeholder="エリアを入力してください"
style="width:300px"
class="form-control" />
図11 @bind:event=”oninput”と@bind:after=”AreaChanged”を組み合わせた最終的なコード
実行して “a”、続けて “b” と入力すると、1文字入力するたびにブレークポイントに到達し、_areaName が “a”→”ab” と更新されていくのが確認できます。画面下のパラメータ表示もリアルタイムに更新されます。
図12 ”ab”と入力すると、1文字ごとに通知が発生し、パラメータ表示もリアルタイムに更新される
ロストフォーカスの通知だけでよい場合
リアルタイムな通知が不要で、ロストフォーカス時の通知だけで十分な場合は、追加した @bind:event=”oninput” を削除しておけば、元通りロストフォーカスのタイミングだけで @bind:after のメソッドが呼ばれるようになります。
図13 @bind:event=”oninput”を削除し、@bind:after=”AreaChanged”のみを残した状態
図14 この状態で実行すると、ロストフォーカスのタイミングでのみAreaChanged()のブレークポイントに到達する
まとめ
@bind は既定で onchange イベントにバインドされているため、同じ要素に @onchange を追加すると属性の重複でコンパイルエラーになります。値が変更された後に何らかの処理を実行したい場合は、@onchange の代わりに @bind:after を使います。@bind:event=”oninput” と @bind:after を組み合わせれば、1文字入力するたびにリアルタイムで通知を受け取ることができ、ロストフォーカス時の通知だけで十分な場合は @bind:event=”oninput” を外しておけばよい、という使い分けになります。
A01_はじめに
A02_バージョンの確認
A03_プロジェクトの作成
A04_アプリの実行
A05_サンプルプログラムの構成
A06_Razorコンポーネント
A07_Razor構文
A08_@pageでURLを指定する
A09_@rendermode
A10_PageTitle
A11_HTMLの見出し
A12_pタグ
A13_単方向データバインド
A14_単方向データバインドの詳細
A15_Bootstrap
A16_ボタンクリックイベント
A17_イベント引数の受け取り方
A18_ここまでのまとめ
B01_新しいWebページを追加する方法
B02_サイドバーから画面を表示する
B03_サイドバーのアイコンを変更する方法
B04_計測値を表示する
B05_変数に置き換える
B06_最新の値でデータを更新する
B07_@usingで通常のC#コードを呼び出す
B08_画面遷移_aタグ
B09_画面遷移_aタグの見た目をボタンにする
B10_画面遷移_NavigationManagerでの遷移
B11_画面間のパラメータの受け渡し方法
B12_EscapeDataStringでエスケープする
B13_複数のパラメータを渡す
B14_任意のパラメータにする
B15_string以外の型をパラメータで使う方法
B16_DateTime型をパラメータで渡す方法
B17_引数2個のURLも型指定に変更する
B18_パラメータ属性をつけるときの注意点
B19_OnParametersSet
B20_OnInitialized
B21_OnInitializedが2回通る問題の対応
B22_ブラウザが開いている間の値を記憶する方法
B23_値の受け渡しとしてのProtectedSessionStorage
B24_非同期を想定したUIの制御
C01_一覧表示
C02_非同期での一覧表示
C03_table-striped
D01_入力エリア
D02_双方向データバインド
D03_入力データをリアルタイムで通知する方法
D04_placeholder
D05_入力エリアの横幅の調整
D06_テキストチェンジイベントを拾う方法
D07_プルダウン
D08_プルダウンのbootstrap
D09_プルダウンの選択している値をデータバインドで操作する
D10_プルダウンにリストの値を表示する
D11_プルダウンに未選択行を入れる
D12_プルダウンの入力を禁止する
D13_プルダウンのチェンジイベントを取得する
D14_チェックボックス
D15_チェックボックスにラベルを付ける
D16_複数のチェックボックスを並べる
D17_ラジオボタン
D18_ラジオボタンのデータバインド
D19_ラジオボタンのチェンジイベント
D20_ラジオボタンにbootstrapを適応する