LoginSignup
6
5

More than 3 years have passed since last update.

multiple属性のinput type='file'にドラッグ&ドロップで複数のファイルを一個ずつ追加していく方法

Last updated at Posted at 2020-10-19

はじめに

ファイルを選択するフォームがある際、
ドラッグ&ドロップができるとスマートで便利ですよね。

mulitiple属性がつくと複数のファイルを一つのフォームで送信が可能です。
そうした上でドラッグ&ドロップで選択する仕様にするのはさほど難しくはありませんでした。
しかし、複数同時にドロップするのではなく、
その複数のファイルを一個ずつドロップできるようにしたかったのですが...

ちょっとツマってしまったので、その解決方法をメモ。

実装

sample.html
<form action="~~~" accept-charset="~~~" method="post">
  <input multiple="multiple" type="file" name="task_images" id="task_images">
  <div id="dropZone" style="width:~~~px;height:~~~px;">
    ここにドラッグ&ドロップ
  </div>
  <input type="submit">
</form>

"~~~~"name="task_images"は例です。
ここでは扱うファイルを画像ファイルを想定してます。
idの"task_images" "dropZone"でそれぞれの要素を取得していきます。

sample.js
  var fileField = document.getElementById('task_images');
  var dropZone = document.getElementById('dropZone');
  var dt = new DataTransfer();

dropZone.addEventListener('drop', (e)=>{
  e.preventDefault();
  dt.items.add(e.dataTransfer.files[0]);
  fileField.files = dt.files;
});

dtに代入されたDataTransferオブジェクトはドラッグ&ドロップされたデータを扱う、保持するために使われます。
なお、safariとIEはnewに対応していないので注意!

e.preventDefault();がないとドロップできないので大事です。

dt.itemsDataTransferItemListオブジェクト
dt.filese.dataTransfer.filesFileListオブジェクトです。
e.dataTransfer.files[0]Fileオブジェクトです。
非常にややこしい!

e.dataTransfer.filesにはドロップされたファイル(Fileオブジェクト)がFileListオブジェクトの中に同時にドロップされた数だけ格納されています。
今回は一つずつドロップし選択するのでe.dataTransfer.files[0]addメソッドでdt.itemsに追加します。
そうするとdt.filesFileListオブジェクトとして変更が反映されています。

最後にinputエレメントであるfileFieldfilesdt.filesに差し替えます。
これでドロップによってinputのファイル選択を追加していくことができます。

最後に

DataTransferにはclearData()など応用の利くメソッドがあるので、
使いようによってはファイル数の制限も実装できます。
画像プレビューにも使うこともできるので、ぜひ調べて見てください。

参考

DataTransfer
Document: drop イベント
FileListは作れる!~file inputの中身も自由自在~

6
5
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
6
5