Blazor WebAssembly 使いまわしが利く部品(表)を作る。

#はじめに
この記事ではよく使われる表を少し使いまわしが利くような部品コンポーネントを作ります。 

#部品コンポーネントの仕様
- 表のカラム名は部品コンポーネントを呼ぶ側で決めたい
- レイアウトは統一したい
- 異なるデータでも使いまわせるようにしたい
- 行をクリックした際の動作を部品コンポーネントを呼ぶ側で決めたい

#部品コンポーネントの内容

```
@typeparam TItem

<table class="table table-hover table-striped">
    <thead class="thead-light rounded">
        <tr>@this.TableHeader</tr>
    </thead>
    <tbody>
        @if (this.Items != null)
        {
            @foreach (var item in this.Items)
            {
                <tr @onclick="@(() => this.RowOnClick.InvokeAsync(item))">@this.RowTemplate(item)</tr>
            }
        }

    </tbody>
</table>

@code {
    [Parameter]
    public EventCallback<TItem> RowOnClick { get; set; }

    [Parameter]
    public RenderFragment TableHeader { get; set; }

    [Parameter]
    public RenderFragment<TItem> RowTemplate { get; set; }

    [Parameter]
    public IList<TItem> Items { get; set; }
}
```

`@typeparam TItem`と記載するとジェネリックを指定できます。
`EventCallback`は呼び出し元で関数を代入出来ます。
`RenderFragment `は呼び出し元で表示内容を決める事が出来ます。


#使い方(コードビハインドで書いています。)
razorコンポーネント

```
@page "/fetchdata"
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using Qiita.Shared
@attribute [Authorize]
@inherits FetchDataModel

<h1>Weather forecast</h1>

<p>This component demonstrates fetching data from the server.</p>

@if (forecasts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <CommonTable Items="forecasts" RowOnClick="this.RowOnClick" TItem="WeatherForecast" >
        <TableHeader>
            <th>Date</th>
            <th>Temp. (C)</th>
            <th>Temp. (F)</th>
            <th>Summary</th>
        </TableHeader>
        <RowTemplate>
            <td>@context.Date.ToShortDateString()</td>
            <td>@context.TemperatureC</td>
            <td>@context.TemperatureF</td>
            <td>@context.Summary</td>
        </RowTemplate>
    </CommonTable>
}
```
Model

```

using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Qiita.Shared;
using Qiita.Shared.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading.Tasks;

namespace Qiita.Client.Pages
{
    public class FetchDataModel : ComponentBase
    {
        [Inject]
        protected HttpClient Http { get; set; }
        protected WeatherForecast[] forecasts;

        protected override async Task OnInitializedAsync()
        {
            try
            {
                forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast");
            }
            catch (AccessTokenNotAvailableException exception)
            {
                exception.Redirect();
            }
        }

        protected void RowOnClick(WeatherForecast value)
        {
            //Rowをクリックした時の処理を部品コンポーネントを呼ぶ側で決める。
        }
    }
}
```

#動作確認
呼び出し元でカラム名/表示するデータ/行クリック時の動作を指定して使えています。
![7.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110251/eae82eb7-fb43-bf95-04d9-72ee7a665b72.gif)


<br>
[Blazor関連のリンク]
[Blazor WebAssembly プロジェクト作成(認証あり)](https://qiita.com/pero_88/items/be142d5d0ba92e5c91d0)
[Blazor WebAssembly 初期プロジェクト構成の入門](https://qiita.com/pero_88/items/ced1028ad536a43fec1d)
[Blazor WebAssembly Postgresを使うまで](https://qiita.com/pero_88/items/23e88a1d2bc3659b9946)
[Blazor WebAssembly コードビハインド](https://qiita.com/pero_88/items/be871f4ac63868f048f0)
[Blazor WebAssembly InputSelectの使い方](https://qiita.com/pero_88/items/3eddcd1aedf8bbc8441b)
[Blazor WebAssembly 部品コンポーネントへ渡した変数とのバインド](https://qiita.com/pero_88/items/f5d70b41337ca6d08dd1)
[Asp.net core Identity 翻訳開始まで](https://qiita.com/pero_88/items/44a66b7ac217f674a7f3)
[Blazor WebAssembly 使いまわしが利く部品(表)を作る。](https://qiita.com/pero_88/items/5e1e3f68d50d941ee36a)