フォームのデータをクリアするボタンを追加したい場合、最も簡単な方法はtype="reset"のボタンを追加することです。これで2つのボタンが必要になり、Blazorの中核概念であるコンポーネントのカプセル化を活用できます。
まず、SharedフォルダにMyButtonというRazorコンポーネントを作成し、ボタンの種類、ボタンのスタイル、ボタン名を表す3つの変数を定義します。これらのプロパティには[Parameter]属性を付ける必要があります。これにより、これらのプロパティの値がこのコンポーネントを呼び出す親コンポーネントから渡されることをBlazorに伝えます。

次に、タイトルの単方向バインディングを削除し、更新時間のdivを<EditForm>の外に移動します。リセットボタンはフォーム全体をクリアするため、更新時間がクリアされるのを防ぐためです。最後に、下部に2つの<MyButton>コンポーネントを使用し、必要なボタンの種類、スタイル、名前を入力します。Blazorは使用されていないParameterを通知し、重複したParameterがあれば警告も表示するので安心です。

リセットボタンを押すと、タイトルと内容がクリアされるのが確認できます。

注意点として、ParameterはrazorとHTML文字列の混在した記述をサポートしていません。そのような場合は、field、property、またはstringメソッドを使用して、結合された文字列をコールバックすることを推奨します。


Parameterに関してもう一つ注意すべき点があります。親コンポーネントが子コンポーネントに値を渡す際、親コンポーネントでStateHasChangedに関連するアクションが発生すると、親コンポーネントと子コンポーネントが再レンダリングされます。ただし、子コンポーネント内で親から渡された値を保存する変数を使うことで回避できます。
上の説明だけではわかりにくいかもしれませんので、Microsoftの例を見てみましょう。まず、拡張コンポーネントを作成します。これは単純で、<div>をクリックするとコンテンツを折りたたんだり展開したりします。また、RenderFragment型のChildContentプロパティも持ち、これにより外部のコンポーネントが表示するコンテンツのテンプレートを決定できます。

次に、Post.razorで2つのExpanderを呼び出します。1つ目はChildContentを使用し、<p>要素を入れています。最後に、@onclick="StateHasChanged"が付いたbuttonがあり、親コンポーネントのStateHasChangedイベントをシミュレートしています。

ページを開くと、2つのExpanderのExpandedが両方ともTrueになっています。

次に、両方のExpanderをクリックすると、Expandedが両方ともFalseになります。

しかし、ここで下部のbuttonをクリックすると、上のExpanderだけがTrueになります。なぜでしょうか?

理由は、親コンポーネントの状態とChildContentプロパティにあります。親コンポーネントの状態が変化すると再レンダリングが発生し、新しいデータが最初の子コンポーネントに渡されるため、ExpandedがTrueにリセットされます。2つ目の子コンポーネントはChildContentを受け取っていないため、再レンダリングされません。
この問題を回避するには、_expandedという名前のプライベートフィールドを定義し、コンポーネントの初期化時に親から渡されたExpandedを保存し、以降のロジックはすべて_expandedに基づいて処理します。

参照:
注:この記事のコードは.NET 6 + Visual Studio 2022でリファクタリングされています。原文のリンクをクリックしてリファクタリング後のコードと比較しながら学習できます。ご一読いただきありがとうございます。原作者を応援してください。