LoginSignup
7
2

More than 3 years have passed since last update.

MudBlazor で作る "input type=file"

Last updated at Posted at 2020-12-09

MudBlazor にはファイル選択のコンポーネントはないっぽい

C# でシングルページ Web アプリケーション (いわゆる "SPA") を実装できる技術、Blazor に関する話題。

前回の投稿で、Blazor 用の Material Design な UI コンポーネントライブラリとして、"MudBlazor" を紹介しました。

MudBlazor を使えば、例えばユーザーのアバター画像ファイルを設定してもらう、といったようなページも、下図のようにそれなりにかっこよく作ることが容易になります。
movie-000.gif
しかし、上図でわかりますが、ファイル選択のコンポーネントは MudBlazor に用意がないようで、そのため、Blazor 標準の <InputFile/> コンポーネント (DOM 上は素の <input type="file"/> としてレンダリングされる) をそのまま配置するだけになっており、ちょっとイケてないです。

そこでもうちょっと頑張って自分で実装を加えることで、下図のようにしてみたいと思います。
movie-001.gif
※下記 URL で実際に動作するライブデモを公開しています。
- https://sample-by-jsakamoto.github.io/MudBlazorInputFile/

基本コンセプトは簡単 ― <label/> 要素を使う

基本コンセプトは簡単です。

<InputFile/> コンポーネントは非表示にしておき、代わりに、その <InputFile/> コンポーネントにリンクする <label/> 要素を配置・表示しておく、というものです。
このためには、<InputFile/> コンポーネントには id 属性を適切に設定しておき、続く <label/> 要素の for 属性にて、<InputFile/> コンポーネントに設定した id 値を指定します。

<InputFile id="avatar-picture-inputfile" Style="display:none;" .../>
<Label for="avatar-picture-inputfile">
  ファイル選択
</Label>

そうすることで、その <label/> 要素をクリックすると、表示上は見えなくなっている <input type="file"/> 要素をクリックしたのと同じ挙動になります。

こうすることで、<input type="file"/> 要素の見た目をいろいろいじるのは難しいところ、代わりに設けた <label/> 要素であれば、その見た目をいい感じにイジれるようになります。

見た目を Material Design な感じにする

ということで早速、"ファイル選択" label 要素を、MudBlazor 提供のボタンコントロールと同じ見た目にしてみます。

MudBlazor の設計・実装のおかげで、これは簡単です。

<label/> 要素に対し、MudBlazor 由来の CSS クラス名を設定するだけです。

今回のケースでは、配色は Primary、外観は Filled、サイズは中のボタンと同じにしたかったため、以下の CSS クラス名を <label/> 要素に適用しました。

  • mud-button-root
  • mud-button
  • mud-button-filled
  • mud-button-filled-primary
  • mud-button-filled-size-medium
  • mud-ripple
...
<Label ... class="mud-button-root mud-button mud-button-filled mud-button-filled-primary mud-button-filled-size-medium mud-ripple">
  ファイル選択
</Label>

こうして CSS クラス名を指定するだけで、<label/> 要素の見た目が、まるっきり、MudBlazor のボタンコントロールと同じにできました。
クリックすると、ちゃんとリップル効果も再現されます。
image.png

入力フィールドっぽくしてみる

大抵の要件では、以上で完了と思います。

が、今回はもう少し踏み込んで、このファイル選択用のユーザーインターフェースを、MudBlazor 提供のテキスト入力コンポーネントっぽく拡張してみます。

具体的には以下の表示要素を付け加えます。

  • 入力項目の名称を表示するキャプション
  • 選択されたファイル名を表示する入力フィールド ("入力" はできないけど)
  • ヘルプテキスト

image.png

入力項目の名称を表示するキャプション

MudBlazor の入力系コンポーネントに表示される入力項目名のキャプションと、同じ見た目のテキストを表示するには、MudBlazor の <MudText/> コンポーネントが使えます。

この <MudText/> コンポーネントの Typo 属性に、Typo.caption を指定すれば OK です。

<MudText Typo="Typo.caption">
    アバター画像ファイル
</MudText>

選択されたファイル名を表示する入力フィールド

これはファイル選択のコンポーネントなので、キーボードから何かテキストを入力するわけではありません。
代わりに、ぱっと見、テキスト入力コンポーネントっぽい見た目で、選択されたファイル名を表示するようにします。

ただのテキスト (選択されたファイルの名前) の表示ですから、先のファイル選択ボタンを <label/> 要素で実装したのと同じように、こちらも <label/> 要素で実現します。

外観の調整ではとりわけ、入力フィールドっぽさを醸し出す、灰色の下線の実装がキモです。

この下線の色の指定は、幸い、MudBlazor が配色情報を CSS 変数として実装していることから、自前の CSS スタイルシート中からも参照可能です。
具体的には、--mud-palette-lines-inputs という CSS 変数名で、入力フィールドの下線の色を参照可能です。

なので、自前の要素で、入力フィールドっぽい下線を引くには、以下のような CSS スタイルを適用すれば OK です。

border-bottom: solid 1px var(--mud-palette-lines-inputs);

ヘルプテキスト

MudBlazor の入力系コンポーネントの下部に表示されるヘルプテキストと、同じ見た目のテキストを表示するには、任意の HTML 要素に対し、mud-input-helper-text CSS クラスを適用すれば OK です。

<div class="mud-input-helper-text">
    ファイルサイズは 512KB までです。
</div>

エラー表示も統合

以上まで実装すると、ファイル種類やサイズについての入力検証結果を、MudBlazor の他の入力フィールド系と同じように、ヘルプテキスト欄に検証エラーメッセージを表示するようにもできます (下図)。

image.png

なお、上図のような入力検証エラー表示にあたり、キャプションや下線、ヘルプテキストの色も変えていますが、この配色も、MudBlazor 由来の CSS 変数で参照・使用できます。

具体的には、CSS 変数 --mud-palette-error を参照することでエラー系の色を参照できます。

まとめ

以上のように少々の手間をかけることで、MudBlazor の他のコンポーネントと並べても違和感のない、見た目 Material Design っていう感じの、ファイル選択のユーザーインターフェースが作れるようになります。

実際の作例全体のサンプルプログラムを、下記 GitHub リポジトリで公開しています。
素の <InputFile/> コンポーネントを配置しているだけの状態から、順に変更を積んでいく様子を 1 コミットずつ残しています。
各コミット間の差分など参考になればと思います。

また、MudBlazor は配色情報を CSS 変数で定義・実装してくれています。
そのお陰で、MudBlazor のテーマシステムにより具体的な配色が変更・カスタマイズされても、今回紹介の実装は何も変更することなく、テーマ配色に追随するのもうれしいところです。

ただし、今回紹介のファイル選択ユーザーインターフェースには、大きな弱点・難点があります。

それは、キーボードから操作できないということです。

まず<label/> 要素にフォーカスがあたりません。
もっとも、この点については、tabindex="0" などと、tabindex 属性を <label/> 要素に指定することでフォーカスがあたるようにはなります。

しかしその先、例えばキーボードのスペースキーの打鍵などでは、ファイル選択のダイアログが開くことがありません。
ここで詰んでしまいます。

この一点、キーボードからの操作ができなくなる点が許容できれば、Material Design なファイル選択のユーザーインターフェースを実現可能、ということになるでしょう。

以上、Learn, Practice, Share!

7
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2