How to Make the File Input 'change' Event Fire for the Same File in JavaScript
A common and frustrating issue when working with <input type="file"> is that the change event will not fire if the user selects the same file multiple times in a row. The event only triggers the first time, leading to unresponsive UI and confused users.
This guide will explain why this happens and teach you the simple, standard solution to ensure the change event fires every single time the user selects a file, even if it's the same one.
The Core Problem: Why the change Event Doesn't Fire
The change event is designed to fire only when the value of an input element changes.
- When the user selects a file for the first time, the input's
valuechanges from empty ('') to the file's path, so thechangeevent fires. - If the user immediately opens the file dialog again and selects the exact same file, the input's
valuedoes not change—it's the same file path as before. Because there is no change, the browser does not dispatch thechangeevent.
The Solution (Recommended): Resetting the Value in the change Handler
The most robust and common solution is to programmatically reset the input's value to null or an empty string at the end of your change event handler. This ensures that the next time the user selects a file, its value will always be different from the now-empty state.
For example, this code works only the first time a specific file is selected.
<input type="file" id="file-input" />
const fileInput = document.getElementById('file-input');
fileInput.addEventListener('change', (event) => {
const file = event.target.files[0];
if (!file) return;
console.log(`Selected file: ${file.name}`);
// The value is now set to the file's path.
// If the user selects this same file again, the value won't change.
});
We can fix the problem by adding one line to the end of the handler.
const fileInput = document.getElementById('file-input');
fileInput.addEventListener('change', (event) => {
const file = event.target.files[0];
if (!file) return;
console.log(`Selected file: ${file.name}`);
// Your file handling logic goes here...
// For example, uploadFile(file);
// THIS IS THE FIX:
// Reset the input's value so the change event will fire again.
event.target.value = null;
});
This is the recommended best practice because it keeps all the related logic within a single event handler, making the code self-contained and easy to understand. Using event.target is also a good practice as it refers directly to the element that triggered the event.
An Alternative Method: Resetting the Value on click
An alternative approach is to reset the input's value every time the user clicks on it, which happens just before they open the file selection dialog.
This solution uses two separate event listeners.
const fileInput = document.getElementById('file-input');
// Main handler for when a file is selected
fileInput.addEventListener('change', (event) => {
const file = event.target.files[0];
if (!file) return;
console.log(`Selected file: ${file.name}`);
// (Your file handling logic here)
});
// Helper handler to reset the value on every click
fileInput.addEventListener('click', (event) => {
// This resets the value before the file dialog opens.
event.target.value = null;
});
This solution also works perfectly but separates the reset logic from the handling logic. While some developers may prefer this separation, the single-handler approach in the previous section is generally more common and intuitive.
Conclusion
The behavior of the file input's change event is intentional, but it often conflicts with the desired user experience.
- The root cause of the issue is that the event only fires when the input's
valuechanges. - The definitive solution is to programmatically reset the input's value after each selection.
- The recommended best practice is to set
event.target.value = nullat the end of yourchangeevent handler, which makes your code clean, self-contained, and reliable.