【Blazor Web App】再利用可能なコンポーネントの作成・利用（.NET 8）

## 目的
Blazor内でコンポーネントを使いまわしたい（モーダルを実装したい）

## 参考
https://learn.microsoft.com/ja-jp/aspnet/core/blazor/components/?view=aspnetcore-9.0

## 理想の形
引数で特定のテキストやスタイルに文字列を挿入しながら、
中身のコンテンツはHTMLで書きたい

```html:TestPage.razor
<Component Title="タイトル" Desc="説明が入る">
    <p>フォームやらなんやらが入る</p>
</Component>
```

## パラメータによる参照

```html
<Component Title="タイトル" Desc="説明が入る"> // ←これ
</Component>
```

>''コンポーネント パラメーター'' によりデータがコンポーネントに渡されます。これらのパラメーターは、[Parameter] 属性を指定したコンポーネント クラス上で、パブリック C# プロパティを使用して定義されます。 次の例では、組み込みの参照型 (System.String) とユーザー定義の参照型 (PanelBody) がコンポーネント パラメーターとして渡されます。

`[Parameter]`をうまく使うといけるらしい。

### テスト実装

```cs:Component.razor
@code {
    [Parameter]
    public string Title { get; set; } = "";
    
    [Parameter]
    public string Desc {get; set; } = "";
}
```

```html:Component.razor
<h2>@Title</h2>
<p>@Desc</p>
```

```TestPage.razor
<Component Title="タイトル" Desc="説明が入る" />
```

### 出力結果

```html:HTML
<h2>タイトル</h2>
<p>説明が入る</p>
```

## レンダリングフラグメントの活用
```html
<Component Title="タイトル" Desc="説明が入る">
    <p>フォームやらなんやらが入る</p> //←これ
</Component>
```

>コンポーネントでは、別のコンポーネントのコンテンツを設定できます。 代入コンポーネントでは、子コンポーネントの開始および終了タグの間にコンテンツを指定します。

>Razorマークアップ内の ChildContent の位置は、コンテンツが最終的な HTML 出力にレンダリングされる場所です。

とのこと。

### テスト実装

```cs:Component.razor
@code{
    [Parameter]
    public RenderFragment? ChildContent { get; set; }
}
```

```html:Component.razor
<div class="child">
    @ChildContent
</div>
``` 

:::note warn
プロパティは`ChildContent`以外の名前を受け付けていません
（他の名称にするとエラーになります）
:::

```hmtl:TestPage.razor
<Component>
    コンテンツが入ります
</Component>
```

### 出力結果

```html:HTML
<div class="child">
    コンテンツが入ります
</div>
```

## Bootstrapモーダルを再利用可能なコンポーネントにする

パラメータとレンダリングフラグメントを組み合わせて、モーダルを作成してみます。
これでスッキリ。

```html:TestPage.razor（コンポーネント利用側）
<Modal ModalTarget="staticBackdrop" ModalTitle="タイトル" SubmitButtonText="実行" CancelButtonText="キャンセル">
  <div class="row mb-3">
    <div class="col-3">
      <label for="area" class="col-form-label d-flex justify-content-between align-items-center">フォーム：</label>
    </div>

    <div class="col-6">
      <input type="text" name="" id="" class="form-control">
    </div>
  </div>
</Modal>
```

```html:Modal.razor
<div class="modal fade" id="@ModalTarget" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1"
  aria-labelledby="staticBackdropLabel" aria-hidden="true">
  <div class="modal-dialog modal-dialog-centered">
    <div class="modal-content p-3">
      <div class="modal-header justify-content-between align-items-start">
        <p></p>
        <div class="text-center">
          <h1 class="modal-title fs-5 text-purple" id="staticBackdropLabel">@ModalTitle</h1>
        </div>
        <button type="button" class="btn-close m-0 p-0" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <div class="conteiner-fluid">
          @ChildContent
        </div>
      </div>
      <div class="modal-footer">
        <button type="submit" class="btn btn-purple">@SubmitButtonText</button>
        <button type="button" class="btn btn-outline-purple" data-bs-dismiss="modal">@CancelButtonText</button>
      </div>
    </div>
  </div>
</div>
```

```cs:Modal.razor
@code {
  [Parameter]
  public string ModalTarget { get; set; } = "";

  [Parameter]
  public string ModalTitle { get; set; } = "";

  [Parameter]
  public string SubmitButtonText { get; set; } = "";
  [Parameter]
  public string CancelButtonText { get; set; } = "";

  [Parameter]
  public RenderFragment? ChildContent { get; set; }
}
```