🔖

ASP.NET Core Blazor で独自の入力コンポーネントを作りたい

2 min read

ASP.NET Core Blazor の現行バージョンでは、まだ入力系コントロールで初期指定するような機能がありません。
日付型限定で @bind:format="yyyy-MM-dd" みたいにすれば書式指定できるのですが他の型では未対応です。

例えばこんな風に書くとエラーになります。

@page "/"

<h1>Hello, world!</h1>

<EditForm Model="this">
    <input @bind="Number" @bind:format="N" />
</EditForm>

@code {
    private decimal Number { get; set; }
}

こんな感じのエラーになります。

1>C:\Users\xxx\MyBlazorApp\MyBlazorApp\Pages\Index.razor(6,19,6,25): error CS1503: 引数 1: は 'decimal' から 'System.DateTime' へ変換することはできません
1>C:\Users\xxx\MyBlazorApp\MyBlazorApp\obj\Debug\net5.0\Razor\Pages\Index.razor.g.cs(110,149,110,156): error CS0029: 型 'System.DateTimeOffset?' を 'decimal' に暗黙的に変換できません

解決策としては、自作入力コントロール作るとかがあります。InputBase を継承して作ればよさそうです。

@using System.Diagnostics.CodeAnalysis
@inherits InputBase<decimal>

<input @bind="CurrentValueAsString" />

@code {
    public string ValidationErrorMessage { get; set; }

    protected override string FormatValueAsString(decimal value)
    {
        return value.ToString("N");
    }

    protected override bool TryParseValueFromString(string value, [MaybeNullWhen(false)] out decimal result, [NotNullWhen(false)] out string validationErrorMessage)
    {
        var x = decimal.TryParse(value, out result);
        validationErrorMessage = x ? "" : ValidationErrorMessage;
        return x;
    }
}

これを使うとこんな感じに出来ます。

@page "/"

<h1>Hello, world!</h1>

<EditForm Model="this">
    <MyInput @bind-Value="Number" />
</EditForm>

@code {
    private decimal Number { get; set; }
}

実行すると、書式指定された感じになります。

まとめ

ということで、こんな風に書式付きのコントロールが出来そうです。
書式指定をパラメーターとして外だしするとより汎用的になりますね。

ただ、そのうち自分の希望的観測では @bind:format="" で普通に日付型以外に対応するかなと思ってるので、そのうち、こんな風に自作する必要はなさそうだなと思いつつメモっておきます。