Clearing <input type='file' /> using jQuery
Solution 1
Easy: you wrap a <form>
around the element, call reset on the form, then remove the form using .unwrap()
. Unlike the .clone()
solutions otherwise in this thread, you end up with the same element at the end (including custom properties that were set on it).
Tested and working in Opera, Firefox, Safari, Chrome and IE6+. Also works on other types of form elements, with the exception of type="hidden"
.
window.reset = function(e) {
e.wrap('<form>').closest('form').get(0).reset();
e.unwrap();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<input id="file" type="file">
<br>
<input id="text" type="text" value="Original">
</form>
<button onclick="reset($('#file'))">Reset file</button>
<button onclick="reset($('#text'))">Reset text</button>
As Timo notes below, if you have the buttons to trigger the reset of the field inside of the <form>
, you must call .preventDefault()
on the event to prevent the <button>
from triggering a submit.
EDIT
Does not work in IE 11 due to an unfixed bug. The text (file name) is cleared on the input, but its File
list remains populated.
Solution 2
Quick answer: replace it.
In the code below I use the replaceWith
jQuery method to replace the control with a clone of itself. In the event you have any handlers bound to events on this control, we'll want to preserve those as well. To do this we pass in true
as the first parameter of the clone
method.
<input type="file" id="control"/>
<button id="clear">Clear</button>
var control = $("#control");
$("#clear").on("click", function () {
control.replaceWith( control = control.clone( true ) );
});
Fiddle: http://jsfiddle.net/jonathansampson/dAQVM/
If cloning, while preserving event handlers, presents any issues you could consider using event delegation to handle clicks on this control from a parent element:
$("form").on("focus", "#control", doStuff);
This prevents the need for any handlers to be cloned along with the element when the control is being refreshed.
Solution 3
Jquery is supposed to take care of the cross-browser/older browser issues for you.
This works on modern browsers that I tested: Chromium v25, Firefox v20, Opera v12.14
Using jquery 1.9.1
HTML
<input id="fileopen" type="file" value="" />
<button id="clear">Clear</button>
Jquery
$("#clear").click(function () {
$("#fileopen").val("");
});
On jsfiddle
The following javascript solution also worked for me on the browsers mention above.
document.getElementById("clear").addEventListener("click", function () {
document.getElementById("fileopen").value = "";
}, false);
On jsfiddle
I have no way to test with IE, but theoretically this should work. If IE is different enough that the Javascript version does not work because MS have done it in a different way, the jquery method should in my opinion deal with it for you, else it would be worth pointing it out to the jquery team along with the method that IE requires. (I see people saying "this won't work on IE", but no vanilla javascript to show how it does work on IE (supposedly a "security feature"?), perhaps report it as a bug to MS too (if they would count it as such), so that it gets fixed in any newer release)
Like mentioned in another answer, a post on the jquery forum
if ($.browser.msie) {
$('#file').replaceWith($('#file').clone());
} else {
$('#file').val('');
}
But jquery have now removed support for browser testing, jquery.browser.
This javascript solution also worked for me, it is the vanilla equivalent of the jquery.replaceWith method.
document.getElementById("clear").addEventListener("click", function () {
var fileopen = document.getElementById("fileopen"),
clone = fileopen.cloneNode(true);
fileopen.parentNode.replaceChild(clone, fileopen);
}, false);
On jsfiddle
The important thing to note is that the cloneNode method does not preserve associated event handlers.
See this example.
document.getElementById("fileopen").addEventListener("change", function () {
alert("change");
}, false);
document.getElementById("clear").addEventListener("click", function () {
var fileopen = document.getElementById("fileopen"),
clone = fileopen.cloneNode(true);
fileopen.parentNode.replaceChild(clone, fileopen);
}, false);
On jsfiddle
But jquery.clone offers this [*1]
$("#fileopen").change(function () {
alert("change");
});
$("#clear").click(function () {
var fileopen = $("#fileopen"),
clone = fileopen.clone(true);
fileopen.replaceWith(clone);
});
On jsfiddle
[*1] jquery is able to do this if the events were added by jquery's methods as it keeps a copy in jquery.data, it does not work otherwise, so it's a bit of a cheat/work-around and means things are not compatible between different methods or libraries.
document.getElementById("fileopen").addEventListener("change", function () {
alert("change");
}, false);
$("#clear").click(function () {
var fileopen = $("#fileopen"),
clone = fileopen.clone(true);
fileopen.replaceWith(clone);
});
On jsfiddle
You can not get the attached event handler direct from the element itself.
Here is the general principle in vanilla javascript, this is how jquery an all other libraries do it (roughly).
(function () {
var listeners = [];
function getListeners(node) {
var length = listeners.length,
i = 0,
result = [],
listener;
while (i < length) {
listener = listeners[i];
if (listener.node === node) {
result.push(listener);
}
i += 1;
}
return result;
}
function addEventListener(node, type, handler) {
listeners.push({
"node": node,
"type": type,
"handler": handler
});
node.addEventListener(type, handler, false);
}
function cloneNode(node, deep, withEvents) {
var clone = node.cloneNode(deep),
attached,
length,
evt,
i = 0;
if (withEvents) {
attached = getListeners(node);
if (attached) {
length = attached.length;
while (i < length) {
evt = attached[i];
addEventListener(clone, evt.type, evt.handler);
i += 1;
}
}
}
return clone;
}
addEventListener(document.getElementById("fileopen"), "change", function () {
alert("change");
});
addEventListener(document.getElementById("clear"), "click", function () {
var fileopen = document.getElementById("fileopen"),
clone = cloneNode(fileopen, true, true);
fileopen.parentNode.replaceChild(clone, fileopen);
});
}());
On jsfiddle
Of course jquery and other libraries have all the other support methods required for maintaining such a list, this is just a demonstration.
Solution 4
For obvious security reasons you can't set the value of a file input, even to an empty string.
All you have to do is reset the form where the field or if you only want to reset the file input of a form containing other fields, use this:
function reset_field (e) {
e.wrap('<form>').parent('form').trigger('reset');
e.unwrap();
}
Here is an exemple: http://jsfiddle.net/v2SZJ/1/
Solution 5
This works for me.
$("#file").replaceWith($("#file").clone());
http://forum.jquery.com/topic/how-to-clear-a-file-input-in-ie
Hope it helps.
![Admin](/assets/logo_square_200-5d0d61d6853298bd2a4fe063103715b4daf2819fc21225efa21dfb93e61952ea.png)
Admin
Updated on October 16, 2020Comments
-
Admin over 3 years
Is it possible to clear an
<input type='file' />
control value with jQuery? I've tried the following:$('#control').attr({ value: '' });
But it's not working.
-
Sampson about 15 yearsI'm confused - I tried $("#inputControl").val("") and it did indeed blank the field. Am I missing something?
-
user14322501 about 13 years@Jonathan, works for me too, but if you set it to anything else it's a security error. Tested in FF4.
-
Chris Stephens about 13 yearsreset() is a JS native method so if you select the form via jQuery you need to take the element out of jQuery scope. $("form#myForm")[0].reset();
-
Casebash over 12 yearsThe annoying thing with this solution is that you have to have the element twice in your code, so if someone changes, for example, the name, you have to change your code twice (which is very easy to forget)
-
metric152 over 12 yearsYou can also use the .clone() method on the field $('#clone').replaceWith($(this).clone());
-
Anonymous almost 12 yearsI coudn't care less about opera. Just wrap it in the form then if you care. I personally don't care and I will use my method.
-
Shawn over 11 yearsHas this been tested in all major browsers?
-
SpoonNZ over 11 yearsIt seems to work fine in the latest version of Chrome/FF/Opera, and in IE8. I can't see any reason why it wouldn't work on anything - the reset option on forms has been around a long time.
-
VoidKing over 11 years@Jonathan It works for you because you did not do it in IE. This security issue is something that only IE stops. Clearing the value regularly works in both Chrome and Firefox, but not IE
-
tomfanning over 11 yearsHi Niraj. Welcome. This answer may well be correct but it could use some explanation.
-
mnsr over 11 yearsIt still doesn't work. It needs to be cleared prior to replacement. So you'd want .val() before .replaceWith(). So it'd be control.val('').replaceWith(...);
-
Trindaz over 11 yearsLooks almost identical to the very problem in the OP
-
nischayn22 over 11 years
-
Timo Kähkönen over 11 yearsWinner! Works in every browser and avoids cloning input field. But if clear-buttons are inside form, please rename
reset()
to eg.reset2()
, because at least in Chrome all fields are cleared if it isreset()
. And add event.preventDefault() after clearing call to prevent submitting. This way:<button onclick="reset2($('#file'));event.preventDefault()">Reset file</button>
. Working example: jsfiddle.net/rPaZQ/23. -
slipheed over 11 years@Timo, I've renamed the function to
resetFormElement
and added a note that you should preventDefault() on the buttononclick
. -
cHao about 11 yearsProblem is, this at least temporarily makes the document invalid. (Forms can not contain other forms.) Whether it currently works or not, it's free to break any time it wants.
-
e-info128 almost 11 yearsis not a ecmascript standard, the value of input type file is a protect property for security reasons.
-
Ninjakannon almost 11 years@cHao, of course this is only true if the input element is actually in a form, which it does not have to be.
-
Gaurav Sharma about 10 yearsdoesn't work in chrome 34 (linux). replaceWith() method works in both browsers (chrome, firefox)
-
Ashish Ratan about 10 yearsok but it will clear the entire form.. not specific file input
-
AlexB almost 10 yearsI don't understand why this answer isn't more upvoted ?!
-
kmacdonald over 9 yearsThis almost works. The one thing you need to do to make this work in Firefox is to use
.pop()
on the array of files instead of setting it to null. this seems to clear out the file properly. -
TheCarver over 9 years@AlexB: Because, as Timo explained, it's overkill just to clear one file input field.
-
Tisch over 8 yearsAs many other posts on here explain, this isn't cross browser friendly.
-
PhiLho over 8 yearsLatest Chrome doesn't like it (
get(0)
is undefined), I had to do.wrap('<form></form>')
, as advised in jQuery doc anyway. -
TheHamstring over 8 yearsFor my understanding which browsers does this fail in?
-
Isaac over 8 yearsThis isn't a good answer at all but the main problem was the really bad attitude
-
Lucky over 8 yearsFails in Internet Explorer as input type file is readonly in IE>
-
Robo Robok over 8 yearsIsn't that easier to call
return false
instead of uglye.stopPropagation()
ande.preventDefault()
pair? It does exactly the same thing: api.jquery.com/on/#event-handler -
fralbo about 8 yearsDon't know if that worked but no more on FF 45.0.2:(
-
JCollerton almost 8 yearsWorks for me! It's worth noting that if you have any event listeners triggered by a change in the file input then you need to reassign them once you have replaced the input.
-
Andrei over 7 years$('input[type=file]').replaceWith($('input[type=file]').clone(true).val(''));
-
Robin Luiten about 7 yearsThis is failing for me in IE11 and Edge 20. It looks like its causing jquery.validator to bomb due to the brief period nested forms exist.
-
slipheed about 7 years@RobinLuiten You may want to try moving the input element up to document.body, wrapping in a
<form>
, resetting that form, then moving the element back to where it came from. -
Robin Luiten about 7 years@slipheed ive gone back to $input.val('') which gave me problems 3 months back when I went to this solution. AT moment the simple solution seems to be working chrome/firefox/edge/ie11/ios safari/android chrome. Your suggestion is a good one and not one I had thought of thanks.
-
naimul64 almost 7 yearsWorks in chrome and firefox. More than enough.
-
Arsha over 6 yearsDue to this function was called with jquery selector. Example
reset($('#targetInput'));
. So, to make IE 11 works just adde.val('');
after thee.unwrap();
line. -
QMaster over 5 yearsAt the first I must notice "The $.browser has been removed from jquery 1.9" but the last two lines (Changing type attribute to text and then set back it to the file) worked. Additionally I tried to set $('#control').val(''); or in javascript document.getElementById(control).value = ''; and worked too and don't know why we shouldn't using this approach!? Finally, I decided to use both of them.