I have a hidden file input element. Is it possible to trigger its select file dialog box from a button's click event?
If you're looking to have your own button to upload a file instead of using <input type="file" />, you can do something like:
<input id="myInput" type="file" style="visibility:hidden" />
<input type="button" value="Show Dialog" onclick="$('#myInput').click();" />
Note that I used visibility: hidden, instead of display: none. You cannot call the click event on a non-displayed file input.
Most answers here are lacking a useful information:
Yes, you can programmatically click the input element using jQuery/JavaScript, but only if you do it in an event handler belonging to an event THAT WAS STARTED BY THE USER!
So, for example, nothing will happen if you, the script, programmatically click the button in an ajax callback, but if you put the same line of code in an event handler that was raised by the user, it will work.
P.S. The debugger; keyword disrupts the browse window if it is before the programmatical click ...at least in chrome 33...
Just for the record, there is an alternative solution that does not require javascript. It is a bit of a hack, exploiting the fact that clicking on a label sets the focus on the associated input.
You need a <label> with a proper for attribute (points to the input), optionnaly styled like a button (with bootstrap, use btn btn-default). When the user clicks the label, the dialog opens, example :
<!-- optionnal, to add a bit of style -->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet"/>
<!-- minimal setup -->
<label for="exampleInput" class="btn btn-default">
Click me
</label>
<input type="file" id="exampleInput" style="display: none" />
I'm not sure how browsers handle clicks on type="file" elements (security concerns and all), but this should work:
$('input[type="file"]').click();
I've tested this JSFiddle in Chrome, Firefox and Opera and they all show the file browse dialog.
Nowadays a hybrid solution like this can have the best experience,
let fileHandle;
async function fileOpen() {
[fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
console.log(await file.text());
}
// The advantage of this is fileHandle can be used to save to
// the opened file itself later, read more on this in https://web.dev/file-system-access/
// in April 2021, window.showOpenFilePicker still not support in Safari
// so one should have this around also
function legacyFileOpen() {
var input = document.createElement('input');
input.type = 'file';
input.onchange = function () {
input.files[0].arrayBuffer().then(function (arrayBuffer) {
console.log(new TextDecoder().decode(arrayBuffer));
});
}
input.click();
}
I wrap the input[type=file] in a label tag, then style the label to your liking, and hide the input.
<label class="btn btn-default fileLabel" data-toggle="tooltip" data-placement="top" title="Upload">
<input type="file">
<span><i class="fa fa-upload"></i></span>
</label>
<style>
.fileLabel input[type="file"] {
position: fixed;
top: -1000px;
}
</style>
Purely CSS Solution.
Natively the only way is by creating an <input type="file"> element and then simulating a click, unfortunately.
There's a tiny plugin (shameless plug) which will take the pain away of having to do this all the time: file-dialog
fileDialog()
.then(file => {
const data = new FormData()
data.append('file', file[0])
data.append('imageName', 'flower')
// Post to server
fetch('/uploadImage', {
method: 'POST',
body: data
})
})
The best solution, works in all browsers.. even on mobile.
<div class="btn" id="s_photo">Upload</div>
<input type="file" name="s_file" id="s_file" style="opacity: 0;">';
<!--jquery-->
<script>
$("#s_photo").click(function() {
$("#s_file").trigger("click");
});
</script>
Hiding the input file type causes problems with browsers, opacity is the best solution because it isn't hiding, just not showing. :)
There is no cross browser way of doing it, for security reasons. What people usually do is overlay the input file over something else and set it's visibility to hidden so it gets triggered on it's own. More info here.
Make sure you are using binding to get component props in REACT
class FileUploader extends Component {
constructor (props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
onChange=(e,props)=>{
const files = e.target.files;
const selectedFile = files[0];
ProcessFileUpload(selectedFile,props.ProgressCallBack,props.ErrorCallBack,props.CompleatedCallBack,props.BaseURL,props.Location,props.FilesAllowed);
}
handleClick = () => {
this.refs.fileUploader.click();
}
render()
{
return(
<div>
<button type="button" onClick={this.handleClick}>Select File</button>
<input type='file' onChange={(e)=>this.onChange(e,this.props)} ref="fileUploader" style={{display:"none"}} />
</div>)
}
}
browse file programatically
function browseFile(accept) {
const promise = resolvingPromise();
const input = document.createElement('input');
input.type = "file";
input.accept = accept;
input.onchange = function (e) {
const files = e.target.files;
promise.resolve(files);
}
setTimeout(function () {
click(input);
}, 0);
return promise;
}
function click(node) {
try {
node.dispatchEvent(new MouseEvent('click'))
} catch (e) {
const evt = document.createEvent('MouseEvents')
evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null)
node.dispatchEvent(evt);
}
}
Using jQuery you can call click() to simulate a click.
This worked for me:
$('#fileInput').val('');
For those who want the same but are using React
openFileInput = () => {
this.fileInput.click()
}
<a href="#" onClick={this.openFileInput}>
<p>Carregue sua foto de perfil</p>
<img src={img} />
</a>
<input style={{display:'none'}} ref={(input) => { this.fileInput = input; }} type="file"/>
<div id="uploadButton">UPLOAD</div>
<form action="[FILE_HANDLER_URL]" style="display:none">
<input id="myInput" type="file" />
</form>
<script>
const uploadButton = document.getElementById('uploadButton');
const myInput = document.getElementById('myInput');
uploadButton.addEventListener('click', () => {
myInput.click();
});
</script>
Related
I am using a form to get a word from a user then displaying it on a web page, here is my js code:
document.addEventListener('DOMContentLoaded', function() {
document.querySelector('form').onsubmit = function() {
const word = document.querySelector('#wrd').value;
const header = document.querySelector('h1');
document.querySelector('h1').innerHTML = word;
}
});
the word flickers for a second then disappears,can you help me?
You must be submitting more than once while cleaning document.querySelector('#wrd').value if that's the only way to fill document.querySelector('h1'). Also, you might be reloading the page, without looking into your code I can't say for sure. The default behaviour of html submit is to reload the page, which would make it empty and appear to "flick"
When you submit a form it's synchronous by default. It takes the action attribute on the form and tries to post data to it. So in order to prevent that you have to capture the event and prevent its default action.
Take an example below for the different forms.
document.addEventListener('DOMContentLoaded', function() {
document.querySelector('#form1').onsubmit = function() {
const word = document.querySelector('#wrd').value;
document.querySelector('h1#first').innerHTML = word;
}
document.querySelector('#form2').onsubmit = function(e) {
e.preventDefault();
const word = document.querySelector('#wrd2').value;
document.querySelector('h1#second').innerHTML = word;
}
});
<form id="form1">
<input type="text" id="wrd" name="content" />
<button type="submit">Regular Submit</button>
</form>
<h1 id="first"></h1>
<hr>
<form id="form2">
<input type="text" id="wrd2" name="content" />
<button type="submit">Submit w/ Default Action Prevented</button>
</form>
<h1 id="second"></h1>
This was discussed a lot, but all of these solutions not work:
$("#getFile").val('');
Nor this:
document.getElementById("getFile").value = "";
When console.log after using one of this - it prints the value of last file attached.
Also cloning not works, although remove the input value.
I want to trigger the event "change" when the user uses the same file after removing. The problem is thatthe value of the input is the last file uploaded.
why not just track the value with another variable and do an if statement? Like var lastUpload = document.getElementById("getFile").value;
then
addEventListener("change", function() {
if(lastUpload === document.getElementById("getFile").value) {
...
}
);
I think this is only possible if you can reset the form as well, see below:
<form action="#" id="form">
<label>Choose File: </label> <input type="file" name="getFile" id="getFile" /><br />
<button type="button" onClick="removeFileName()">Clear File</button>
</form>
And JS:
function removeFileName(){
form.reset();
var field = document.getElementById("getFile");
console.log(field.value);
}
I have an input text that has to be something in it for the form to work.
So I wish to add some functionality to the Confirm button that checks if the input field is empty, and if so, recolor the border of that input.
I'm doing the following:
$(function mainListeners () {
"use strict";
var confirm = $('#addNewConfirm');
var cancel = $('#addNewCancel');
var eventBox = $('#eventname_input');
console.log("RUNS!!");
confirm.onclick = function (e) {
if (eventBox.val() == ''){
//so if we have an empty event
//recolor borders.
console.log("CHANGES!!");
eventBox.css('border-color','#d81919');
}else {
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="yesno IFlexible">
<button id="addNewConfirm" >Confirm</button>
<button id="addNewCancel">Cancel</button>
</div>
<div >
<label>Event:</label>
<input id="eventname_input" type="text" />
</div>
Here I get no errors and I always see the RUNS!! message, so my script is attached. However, I never see the CHANGES!! message, so the condition eventBox.val() == '' is never true. I looked up the internet on how to check if an input text's text is empty, and this is what I found, and it clearly isn't working.
How can I sort out this recolor of border if the input has no text?
Use JQuery click() function instead of onclick like so:
$(document).ready(function() {
var confirm = $("#addNewConfirm");
var cancel = $("#addNewCancel");
var eventBox = $("#eventname_input");
console.log("RUNS!!");
confirm.click(function(e) {
if (!eventBox.val()) {
console.log("CHANGES!!");
eventBox.css("border-color", "#d81919");
} else {
eventBox.css("border-color", 'inherit');
// whatever you want
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="yesno IFlexible">
<button id="addNewConfirm">Confirm</button>
<button id="addNewCancel">Cancel</button>
</div>
<div>
<label>Event:</label>
<input id="eventname_input" type="text" />
</div>
Try using either the Jquery method of setting a click event (.click()) or the vanilla JS way of retrieving a DOM element(document.getElementById()).
Below is a working example of changes!! getting called.
$(function mainListeners () {
"use strict";
var confirm = document.getElementById('addNewConfirm'); //GET DOM ELEMENTS THIS WAY OR SEE BELOW FOR CLICK
var cancel = $('#addNewCancel');
var eventBox = $('#eventname_input');
console.log("RUNS!!");
confirm.onclick = function (e) {//OR CHANGE THIS TO CLICK()
if (eventBox.val() == ''){
//so if we have an empty event
//recolor borders.
console.log("CHANGES!!");
event.css('border-color','#d81919');
}else {
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="yesno IFlexible">
<button id="addNewConfirm" >Confirm</button>
<button id="addNewCancel">Cancel</button>
</div>
<div >
<label>Event:</label>
<input id="eventname_input" type="text" />
</div>
The fact is that onclick is vanilla Javascript and you are trying to use it on the confirm jQuery object.
In order to fix it, you can use confirm[0].click = function(e) syntax or confirm.click(function (e). I suggest you to use jQuery syntax: if you load this library you are encouraged to use it in order to strengthen readability.
I have a input type=file which works correctly on Chrome but when I am trying it on Internet Explorer 9, clicking on the button do not work but then if I refresh the page it will work. And if i try again after that, it will not work anymore....
HTML
<div class="input-group">
<span class="input-group-btn">
<span class="btn btn-primary btn-file">
Browse <input type="file" id="inputLogo" />
</span>
</span>
<input type="text" class="form-control" readonly ng-model="logoName" id="logoName" />
</div>
CONTROLLER (ANGULARJS)
$("#inputLogo").fileReader({
filereader: "js/lib/FileReader/filereader.swf"
});
$("#inputLogo").on('change', function (e) {
var image = e.target.files[0];
console.log("IMAGE:" + image);
$scope.logoName = image.name;
var filereader = new FileReader();
filereader.onload = function (e) {
var custLogo = e.target.result;
while (custLogo.charAt(0) != "4") {
custLogo = custLogo.substr(1);
}
custLogo = custLogo.substr(1);
custLogo = custLogo.substr(1);
$scope.logoBase64 = custLogo;
}
filereader.readAsDataURL(image);
});
EDIT
When I click on the "browse" button nothing happens. No dialog pop-up, no console errors.
Everything works well on another page.
The only difference I see between those two is that on the buggy one my input is in a table row and the table is inside a ng-show (angularjs)
If the second time you try, you choose the same file, the change event isn't triggered because the value doesn't change. You have to reset the input value after the first time :
e.target.value = '';
Is there any chance to detect every file selection the user made for an HTML input of type file element?
This was asked many times before, but the usually proposed onchange event doesn't fire if the user select the same file again.
Set the value of the input to null on each onclick event. This will reset the input's value and trigger the onchange event even if the same path is selected.
var input = document.getElementsByTagName('input')[0];
input.onclick = function () {
this.value = null;
};
input.onchange = function () {
console.log(this.value);
};
<input type="file" value="C:\fakepath">
Note: It's normal if your file is prefixed with 'C:\fakepath'. That's a security feature preventing JavaScript from knowing the file's absolute path. The browser still knows it internally.
Use onClick event to clear value of target input, each time user clicks on field. This ensures that the onChange event will be triggered for the same file as well. Worked for me :)
onInputClick = (event) => {
event.target.value = ''
}
<input type="file" onChange={onFileChanged} onClick={onInputClick} />
Using TypeScript
onInputClick = ( event: React.MouseEvent<HTMLInputElement, MouseEvent>) => {
const element = event.target as HTMLInputElement
element.value = ''
}
<form enctype='multipart/form-data'>
<input onchange="alert(this.value); this.value=null; return false;" type='file'>
<br>
<input type='submit' value='Upload'>
</form>
this.value=null; is only necessary for Chrome, Firefox will work fine just with return false;
Here is a FIDDLE
In this article, under the title "Using form input for selecting"
http://www.html5rocks.com/en/tutorials/file/dndfiles/
<input type="file" id="files" name="files[]" multiple />
<script>
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
// files is a FileList of File objects. List some properties.
var output = [];
for (var i = 0, f; f = files[i]; i++) {
// Code to execute for every file selected
}
// Code to execute after that
}
document.getElementById('files').addEventListener('change',
handleFileSelect,
false);
</script>
It adds an event listener to 'change', but I tested it and it triggers even if you choose the same file and not if you cancel.
handleChange({target}) {
const files = target.files
target.value = ''
}
<input #myInput type="file" id="imgFile" (click)="$event.target.value=null"
(change)="detectUploadedImage($event)" accept="image/*" />
Clearing the value of 0th index of input worked for me. Please try the below code, hope this will work (AngularJs).
scope.onClick = function() {
input[0].value = "";
input.click();
};
Usage of two way binding worked for me if you are working with Angular.
Here is my HMTL
<input type="file" #upload name="upload" [(ngModel)]="inputValue"(change)='fileEvent($event)'/>
and TS..
#ViewChild('upload') uploadBtn: HTMLElement;
fileEvent(e: any){
//file upload part...
this.inputValue = "";
}
The selected answer (using state to set input value null) gave me an error.
I use empty strings instead
const [fileValue, setFileValue] = React.useState("")
<input
onClick={() => {
setFileValue("");
}}
type="file"
value={fileValue}
onChange={handleAddFile}
/>
Do whatever you want to do after the file loads successfully.just after the completion of your file processing set the value of file control to blank string.so the .change() will always be called even the file name changes or not. like for example you can do this thing and worked for me like charm
$('#myFile').change(function () {
LoadFile("myFile");//function to do processing of file.
$('#myFile').val('');// set the value to empty of myfile control.
});