2

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')
    }
}
E_net4
  • 27,810
  • 13
  • 101
  • 139
Can Poyrazoğlu
  • 33,241
  • 48
  • 191
  • 389

4 Answers4

6

I think there might be something else which is an issue over here, because when in below snippet alert box is coming up everytime a new file is selected.

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

function onSelectedFileChange(e) {
    file = e.target.files[0];
    alert('new file');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" id="my-input" name="my-input" class="hidden" />

Is it possible that handleFile() function might be breaking second time?

lavish
  • 2,154
  • 1
  • 10
  • 9
  • `handleFile` doesn't touch the input element at all. It just reads the `file` object and assigns it to a variable, and I don't touch anything inside that object either. I just store it to read the name and perform the upload if the user clicks upload (which isn't the case here). – Can Poyrazoğlu Feb 28 '17 at 09:21
2

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.

Community
  • 1
  • 1
Niki van Stein
  • 10,564
  • 3
  • 29
  • 62
  • `$("#my-input")[0]` returns underlying DOM element, thus OP is using is correctly.However attaching event using `.on()` is preferred – Satpal Feb 28 '17 at 09:04
  • Yes, as @Satpal just said, I was trying to get the DOM element instead of jQuery object. I don't have any other elements with the same ID. Anyway, your solution worked, but I'd really want to know why my solution wasn't working. – Can Poyrazoğlu Feb 28 '17 at 09:06
  • @CanPoyrazoğlu aah ok, in that case the [0] should indeed work. Are you adding the input dynamically or changing the inner html of the input? Because then the `.on()` method works but the js version does it only once. (see http://stackoverflow.com/questions/7179627/files-input-change-event-fires-only-once) – Niki van Stein Feb 28 '17 at 09:10
  • @BasvanStein I'm not adding it dynamically, it's just a static, visually hidden (using CSS) input element. The only thing is that I'm triggering it indirectly (for visual purposes, displaying another div and invoking the hidden input's click event from div) but I've also tried un-hiding it and clicking it directly, there wasn't any difference. – Can Poyrazoğlu Feb 28 '17 at 09:13
  • Signature for `jQuery.on()` method is build for such dynamic events is different. @CanPoyrazoğlu you should share the code of `handleFile()` method too – Satpal Feb 28 '17 at 09:13
  • @Satpal I've added the method's implementation to the question. – Can Poyrazoğlu Feb 28 '17 at 09:25
  • @CanPoyrazoğlu, I have downvoted the answer and reason is simple reason provided are incorrect. I am still looking for why it was not working. I have posted comment before the answer. `$("#my-input").on('change', onSelectedFileChange);` will not handle dynamic element and its not required here and `.change(handler)` is short hand of `.on('change', handler);` I my opinion you should not have accept the answer – Satpal Feb 28 '17 at 09:34
  • @Satpal well, next time provide the answer as an actual answer (before someone else, of course), not a comment. I can't accept comments, only answers :) you are right about finding the actual cause, but it doesn't change the fact that this answer has solved my problem, therefore I've upvoted and accepted it. – Can Poyrazoğlu Feb 28 '17 at 09:52
  • 1
    @CanPoyrazoğlu You are right about the dynamic elements, I have edited my answer to show the correct info. (my bad..). – Niki van Stein Feb 28 '17 at 09:53
  • @CanPoyrazoğlu, I didn't provided answer as I didn't think its the reason for the problem [lavish](http://stackoverflow.com/a/42504384)'s answer proves it. – Satpal Feb 28 '17 at 09:57
  • @Satpal next time upvote what you think should be upvoted then. downvoting questions and helpful answers won't give you anything. – Can Poyrazoğlu Feb 28 '17 at 10:00
  • @Satpal I am not "angry" or anything :) I just want things to be done the correct way, that's it :) if something deserves a downvote, of course you should. I honestly thought that it wasn't the case this time :) – Can Poyrazoğlu Feb 28 '17 at 10:05
0

little change to your code like this

$("#my-input").onchange = onSelectedFileChange;
Amit Yadav
  • 481
  • 3
  • 11
0

I've got the same problem both in my code and the Code Snippet that lavish provided. Therefore, if lavish's Code Snippet works for others, then it must be a browser issue. Maybe Chrome has an issue with the input-file type?

What I've checked: console.log($('#input')[0].files[0]) provides a list of the attached files to the input, and it is definitely cleared with $('#input').val('').empty().

So even with everything reset per every method, a second onChange does not trigger with my version of Chrome (win11).

Instead, I've looked for an alternative to onchange.. and found that oninput does the job.

Just replace onchange to oninput.. problem solved.