ふつうにvalue
を書くことができない<input type="file">
ですが、ブラウザによっては動的な設定もほぼ自由に行えることが判明しました。
<input type="file">
へ値を設定する
入力するものがファイルである以上、<input type="file">
に対してvalue
は(空にするvalue = ''
を除けば)使えないのですが、別ルートとしてfiles
というプロパティがあります(MDN)。ここには選択したファイルのリスト(multiple
でなければ1つだけ)が入ったFileList
オブジェクトが入っていて、また代入することで設定が可能です。
FileList
って、何?
ところが、files
に代入するものもFileList
オブジェクトでなければならず、代わりにFile
の配列を持ってきてもエラーになります。しかも、new FileList
も動かないため、一見すると他の<input type="file">
から持ってくる、ぐらいの動作しかできないようにも見えます。実際、昔はそうでした。
裏口から作る~DataTransfer
ここで登場するのがDataTransfer
です。これは、ドラッグアンドドロップで動かしているデータを持つためのオブジェクトです。ファイルを投げ込むような動作も存在する以上、このオブジェクトもfiles
としてFileList
を持っています。
そして、どういうわけか、DataTransfer
はnew
できます。なので、DataTransfer
経由でFileList
をゼロから作ることが可能となります。
const dt = new DataTransfer();
dt.items.add(file);
const list = dt.files;
なお、iOS(とIE)はこの方法に対応していませんので、要注意です(Can I use)。
動作例
<input type="file" multiple>
で一気に選んだファイルを、1つ1つ<input type="file">
に分配するような例を実装しました。
See the Pen DataTransfer経由でFilesを作る by Jkr2255 (@jkr2255) on CodePen.
その他
DataTransfer
経由でFileList
の作成が可能となったため、new FileList
ができないことが有害無益となってしまい、これも可能とする動きもあるようです。