Blazorでテキストボックス間の同期
片方のテキストボックスに入力した内容を、もう片方のテキストボックスに同期的に表示したい。
というのはまったくニーズが無い話とは思います。
環境
- Windows 10 Pro 1809
- Visual Studio 2019 16.0.3
- .NET Core 3.0.1 preview5
準備
さて、まずはClient Side Blazor
のテンプレートを使ってソリューションを作成します。
次に空のページを一つ作りましょう。
Pages
フォルダーで右クリックして追加
> クラス
として、名前を「SyncTextBox.razor」という名前をつけます。
作ったらこのSyncTextBox.razorに書かれているC#のコードを削除します。 これで準備完了です。
ちなみに、なぜこんな回りくどいことをやっているかというと、私のプレビュー×プレビューな環境ではRazorページの自動生成はどころかMVCの各種スキャフォールディングといった自動生成が全く使えないからです。
そのうち修正されると思います。
まずはテキストボックスの同期
それでは、まずはこんなふうに書いてみましょう。
@page "/synctextbox" <p>エンターを押した時点で出力側が更新</p> <p> 入力1 <input type="text" bind="@Text1" /> </p> <p> 出力1 <input type="text" value="@Text1" /> </p> @functions{ string Text1 { get; set; } }
そうしたら実行して、http://localhost:{ポート番号}/synctextbox
をブラウザで開いてみましょう。
以下のようなページが表示されます。
2つあるテキストボックスのうち、上のテキストボックスに文字を入力してエンターキーを押してみましょう。
下のテキストボックスに同じテキストが表示されたと思います。
コードブロックに用意したText1
プロパティを介して入力1のテキストを出力1のテキストボックスに表示させています。
入力側のテキストボックスではbind
属性を使用してText1
プロパティと双方向バインディングしています。
これで入力側のテキストボックスの内容がText1
プロパティに反映されます。
これに対して、出力側のテキストボックスではvalue
属性を使ってText1
プロパティの値を表示させています。
value
属性はプロパティからビューへの単方向バインディングです。
今回の場合、bind
属性を使っても良いのですが、せっかくなのでvalue
にしました。
この例では、出力側への反映のタイミングは入力側のテキストボックスでエンターが入力されたときです。 エンターが入力されるまでは出力側のテキストボックスには変化はありません。
こんなふうに入力内容が確定したら他の場所で反映させる、ということが簡単にできます。
リアルタイムな同期
それでは、2つのテキストボックス間をリアルタイムに同期させるにはどうしたらいいでしょうか。
その場合はbind
属性ではなく、oninput
属性を使うと実現できます。イベントですね。
これはテキストボックスに何かしら入力があった場合に発火するイベントです。
このイベントを使って以下のように書くことができます。
@page "/synctextbox" <p>エンターを押した時点で出力側が更新</p> <p> 入力1 <input type="text" oninput="@(ui=> { Text2 = (string)ui.Value; })" /> </p> <p> 出力1 <input type="text" value="@Text2" /> </p> @functions{ string Text2 { get; set; } }
oninput
イベントはUIChangeEventArgs
型の引数を一つとり、その中にinput要素の値を指すValue
プロパティがあります。
このValue
プロパティを使ってText2
プロパティを更新することで、2つのテキストボックス間のリアルタイム同期を行っています。
テキストボックス間で双方向の同期
2つのテキストボックスがそれぞれoninput
属性でText3
プロパティを更新してvalue
属性で値を表示するようにすると、双方向同期ができます。
@page "/synctextbox" <p>エンターを押した時点で出力側が更新</p> <p> 入力1 <input type="text" oninput="@(ui=> { Text2 = (string)ui.Value; })" value="@Text2" /> </p> <p> 出力1 <input type="text" oninput="@(ui=> { Text2 = (string)ui.Value; })" value="@Text2" /> </p> @functions{ string Text2 { get; set; } }