BlazorでMarkDownEditorを作る(その2)

2019年11月14日

今回は、その1で作ったStep1コンポーネントをベースにStep2コンポーネントを作っていく。
今回やりたいことは、ボタン経由ではなくて、文字が入力されたらHTMLに変換して表示するということをする。
今回の内容はGitHubにあります。

onchangeイベント,oninputイベントを使って、入力と一緒にMarkDownをHTMLに変換する

ここで、普通に考えると、onchangeイベントを使いたくなる。
しかし、これがうまくいかなかった。
調べてみると、こちらに非常に詳しく理由が書かれていた。
それにここめちゃわかりやすい。
解決策としては、@bind使うときは、onchangeイベント使わないで、 oninput イベントを使えばよいとのこと。

公式のコンポーネントの項目を読んでいると、@bindのイベントを変更することも可能らしい。
@bind使うと、自動的にonchangeがデフォルトのイベントとして登録される。
デフォルトのイベントを例えばoninputにしたければ、こんな感じにする。

<input type="text" @bind-value="@input" @bind-value:event="oninput"/>

MSのドキュメントでも書いていたけど、@bind-value:eventを使うときは、@bind-valueと書いてやる必要がある。@bindとのセットではビルドエラーとなった。

@bind 構文を使用した onchange イベントの処理に加えて、event パラメーター (@bind-value:event) を使用して@bind-value属性を指定することで、プロパティまたはフィールドを他のイベントを使用してバインドできます。 次の例では、oninput イベントの CurrentValue プロパティをバインドします。

https://docs.microsoft.com/ja-jp/aspnet/core/blazor/components?view=aspnetcore-3.0

ではさっそく、やっていく。

@using Markdig
<div>
    <input type="text" @bind="@input" @oninput="InputEvent"/>
    <div>@((MarkupString)outputTxt)</div>
</div>

@code {
    public string input { get; set; } = string.Empty;
    public string outputTxt { get; set; }
    private void InputEvent(ChangeEventArgs e)
    {
        this.outputTxt = Markdown.ToHtml(this.input);
    }
}

これinputのところに初期値入れたのは、onchangeイベントがoninputイベントより先に発生して、this.inputがnullでヌルポになったから。

public string input { get; set; } = string.Empty;

これイベントの発生順気にしないといけない。

次に遅そうなイベントをインテリセンスから選んでみる。
onkeyupだ。イベントArgsもちゃんと合わせてやる。

@using Markdig
<div>
    <input type="text" @bind="@input" @onkeyup="InputEvent"/>
    <div>@((MarkupString)outputTxt)</div>
</div>

@code {
    public string input { get; set; } = string.Empty;
    public string outputTxt { get; set; }
    private void InputEvent(KeyboardEventArgs e)
    {
        this.outputTxt = Markdown.ToHtml(this.input);
    }
}

これでもだめ。なんだろう。これはさすがにイケルと思った。
しかたない。bindのイベントを変える。

@using Markdig
<div>
    <input type="text" @bind-value="@input" @bind-value:event="oninput" @onchange="ChangeEvent"/>
    <div>@((MarkupString)outputTxt)</div>
</div>

@code {
    public string input { get; set; } = string.Empty;
    public string outputTxt { get; set; }
    private void ChangeEvent(ChangeEventArgs e)
    {
        this.outputTxt = Markdown.ToHtml(this.input);
    }
}

あれ?これもなんか違う。カーソルアウトして初めて変化する。
ブレークポイント置いてみると、確かに文字入力しただけではブレークしない。
んじゃ、やっぱ違うイベント!!

@using Markdig
<div>
    <input type="text" @bind-value="@input" @bind-value:event="oninput" @onkeyup="OnKeyUpEvent"/>
    <div>@((MarkupString)outputTxt)</div>
</div>

@code {
    public string input { get; set; } = string.Empty;
    public string outputTxt { get; set; }
    private void OnKeyUpEvent(KeyboardEventArgs e)
    {
        this.outputTxt = Markdown.ToHtml(this.input);
    }
}

お!これならいい感じ!
諸々時間制限もあるので、今日はここまでにする。
もう少しどのイベントにするかとか、ちゃんと考えないとね。

今日のまとめ

まずbindのイベントをoninputにして、bindのタイミングを少し早めてやる。
マークダウンからHTMLを生成するためのイベントは、OnKeyUpEventを使う。

C#Blazor, C#

Posted by takumioda