Search code examples
javascripthtmlfile-uploadhtml-input

HTML input file onchange not triggering second time for different file


I've seen many questions regarding input file elements not triggering the onchange event the second time with the same file, but my case is not that. My onchange handler is not trigerred when a different file is selected too.

I select a file, then if I try to select another file, it just doesn't work. The file selection dialog comes up, I select my (different) file, and that's it. the onchange handler, which is called at the first time, is not called again. Nothing happens when I select the file.

Here is my JS:

<input type="file" id="my-input" name="my-input" class="hidden" />

(on jQuery): $("#my-input")[0].onchange = onSelectedFileChange;

function onSelectedFileChange(e) {
    file = e.target.files[0];
    handleFile(); //my code that processes the file, has nothing to do with the input element.
}

I've also tried re-adding the onchange in handleFile method too (e.g. copying $("#my-input")[0].onchange = onSelectedFileChange; into it), but it doesn't seem to work either. After I select a file, my input method's onchange property is set to null and even if I set it again explicitly, it somehow stays null.

Why would this be happening? This happens to be a cross-browser situation.

UPDATE: Here is the handleFile method:

//file is in the global scope, from the previous method
function handleFile() {
    var lowerName = file.name.toLowerCase();
    if (lowerName.endsWith('.pdf') || lowerName.endsWith('.doc') || lowerName.endsWith('.docx')) {
        $("#file-name").text(file.name);
    } else {
        file = null;
        alert('Please select a valid file')
    }
}

Solution

  • Instead of using

    $("#my-input")[0].onchange = function
    

    You can use the jquery equivalent

    $("#my-input").change(function)
    

    or

    $("#my-input").on('change',function)
    

    Though all of them should do roughly the same, it is strange that your code is not working the way it was. You can change it with '.on' in such a way that it also takes into account dynamically added elements using

    $("body").on('change', '#my-input', onSelectedFileChange);
    

    Edit

    The [0] notation indeed selects the underlying DOM element such that you can use javascripts onchange (instead of the jquery equivalent change()). Most likely in your code you update the DOM element (innerHTML or similar) which causes it to loose the onchange listener from javascript.