😳

inputのfileで2回同じものを選択するとchangeが効かない

2021/09/24に公開

inputタグのchangeイベントをキャッチする時に、「同じファイルを選択する」時changeイベントが発火しない問題がありました。

これは、1度目の選択で選ばれたものがeventのvalueに入ってしまってる事により
反応しないという理由でした。

超超簡易サンプルコード

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style></style>
  </head>
  <body>
    <input type='file' id='file-input'></input>
    <script src="./index.js"></script>
  </body>
</html>
js
(() => {
  const input = document.getElementById('file-input');
  input.addEventListener('change', () => {
    console.log('change');
  })
})();

ここで、inputのボタンで2回同じファイルを選択します。
そうすると2回目の選択時には、「change」がコンソールに表示されないと思います。

なので、以下のようにeventに含まれるvalueを空にすることで解消されます。

js
(() => {
  const input = document.getElementById('file-input');
+  input.addEventListener('click', (e) => {
+    e.target.value = '';
+  })
  input.addEventListener('change', () => {
    console.log('change');
  })
})();

同じファイル選ばなくない?

同じファイルを選択する必要は本来であればあまりないように思います。

しかし、選択されるたびに選択されたファイルに関するダイアログなどをchangeイベントをトリガーに表示する際、一度ダイアログの中でキャンセルしたとしても、inputの中にはファイルの情報が格納されてしまいます。

もし次に同じファイルを選択して、ダイアログを表示させたいとしても、選択されたファイルと同じだとchangeイベントが発火しないので、ダイアログが表示されないなどのユースケースがありました。

そのため、こういった初期化処理を挟む事で解消が必要になってきます。

参考

https://rennnosukesann.hatenablog.com/entry/2018/05/23/082920

Discussion