Cancel event on input type=file
A bit of research indicates that there is no way to detect when Cancel is selected in the File Selection dialog window. You can use onchange
or onblur
to check if files have been selected or if something has been added to the input value
.
This could look like: https://jsfiddle.net/Twisty/j18td9cs/
HTML
<form>
Select File:
<input type="file" name="test1" id="testFile" />
<button type="reset" id="pseudoCancel">
Cancel
</button>
</form>
JavaScript
var inputElement = document.getElementById("testFile");
var cancelButton = document.getElementById("pseudoCancel");
var numFiles = 0;
inputElement.onclick = function(event) {
var target = event.target || event.srcElement;
console.log(target, "clicked.");
console.log(event);
if (target.value.length == 0) {
console.log("Suspect Cancel was hit, no files selected.");
cancelButton.onclick();
} else {
console.log("File selected: ", target.value);
numFiles = target.files.length;
}
}
inputElement.onchange = function(event) {
var target = event.target || event.srcElement;
console.log(target, "changed.");
console.log(event);
if (target.value.length == 0) {
console.log("Suspect Cancel was hit, no files selected.");
if (numFiles == target.files.length) {
cancelButton.onclick();
}
} else {
console.log("File selected: ", target.value);
numFiles = target.files.length;
}
}
inputElement.onblur = function(event) {
var target = event.target || event.srcElement;
console.log(target, "changed.");
console.log(event);
if (target.value.length == 0) {
console.log("Suspect Cancel was hit, no files selected.");
if (numFiles == target.files.length) {
cancelButton.onclick();
}
} else {
console.log("File selected: ", target.value);
numFiles = target.files.length;
}
}
cancelButton.onclick = function(event) {
console.log("Pseudo Cancel button clicked.");
}
I suggest making your own cancel or reset button that resets the form or clears the value from the input.
How can I detect that the Cancel Button has been clicked on a input type=file / Select File Dialog?
I've invested countless hours looking for a solution. And now I want to share my solution with you.
I use three event handlers:
onchange
event on the file input: To detect when a file has been selected.onfocus
event onwindow
: To detect when the Select File Dialog has been closed.onmousemove
event ondocument.body
: To detect when the interaction is not blocked anymore. Only when this event is called, you can be sure that theonchange
event of the input element has been called.
The first two points are obvious and you find them in most proposed solutions. But the crucial point is number 3. In other solutions I sometimes faced the problem that I selected a file, but this selected file has not been propagated to the onchange
event handler before window's got focus.
To make a long story short, here's my implementation:
TypeScript solution:
public static selectFile(accept: string = null): Promise<File> {
return new Promise<File>(async resolve => {
const fileInputElement = document.createElement('input') as HTMLInputElement;
fileInputElement.type = 'file';
fileInputElement.style.opacity = '0';
if (accept) fileInputElement.accept = accept;
fileInputElement.addEventListener('change', () => {
const file = fileInputElement.files[0];
console.log('File "' + file.name + '" selected.');
document.body.removeChild(fileInputElement);
resolve(file);
});
document.body.appendChild(fileInputElement);
setTimeout(_ => {
fileInputElement.click();
const onFocus = () => {
window.removeEventListener('focus', onFocus);
document.body.addEventListener('mousemove', onMouseMove);
};
const onMouseMove = () => {
document.body.removeEventListener('mousemove', onMouseMove);
if (!fileInputElement.files.length) {
document.body.removeChild(fileInputElement);
console.log('No file selected.');
resolve(null);
}
}
window.addEventListener('focus', onFocus);
}, 0);
});
}
JavaScript solution:
function selectFile(accept = null) {
return new Promise(async resolve => {
const fileInputElement = document.createElement('input');
fileInputElement.type = 'file';
fileInputElement.style.opacity = '0';
if (accept) fileInputElement.accept = accept;
fileInputElement.addEventListener('change', () => {
const file = fileInputElement.files[0];
console.log('File "' + file.name + '" selected.');
document.body.removeChild(fileInputElement);
resolve(file);
});
document.body.appendChild(fileInputElement);
setTimeout(_ => {
fileInputElement.click();
const onFocus = () => {
window.removeEventListener('focus', onFocus);
document.body.addEventListener('mousemove', onMouseMove);
};
const onMouseMove = () => {
document.body.removeEventListener('mousemove', onMouseMove);
if (!fileInputElement.files.length) {
document.body.removeChild(fileInputElement);
console.log('No file selected.');
resolve(null);
}
}
window.addEventListener('focus', onFocus);
}, 0);
});
}
ReactJS - How to detect when cancel is clicked on file input?
Well, this is probably what I would do but I don't really like it, also I think that the whole idea of performing something because the user decided not to upload a file isn't a good user experience so use it wisely.
fileInputClicked(event){
let file = event.target.files[0];
console.log("File is Selected", file);
window.removeEventListener('focus', this.handleFocusBack);
}
handleFocusBack(){
console.log('focus-back');
window.removeEventListener('focus', this.handleFocusBack);
}
clickedFileInput(){
window.addEventListener('focus', this.handleFocusBack);
}
render() {
return (
<div>
<div>
<p>Hello world</p>
<input onClick={this.clickedFileInput} type="file" onChange={this.fileInputClicked}/>
</div>
</div>
);
}
This way, when the user decides to close the file input, he focuses back on the window and you get the handleFocusBack
functionality you want and when he adds a file he goes to the fileInputClicked
.
Afaik, there is no 'out of the box' mechanism to achieve what you want.
Related Topics
Html and CSS Are Not Linking/ Communicating
How to Align Two Submit Button on Same Line
How to Clear Input Field After Submitting Data in Angular
How to Hide Link Information At the Bottom Left/Right of the Browser on Hover
How to Create an HTML Table With a Fixed/Frozen Left Column and a Scrollable Body
A Div With Auto Resize When Changing Window Width\Height
Max Parallel Http Connections in a Browser
Does Ul Have Default Margin or Padding
Left Column and Stacked Right Column Using Flexbox Css
How to Set Max-Length in an Html5 "Input Type=Number" Element
How to Set Space Between Contained Divs
How to Remove Outline in Bootstrap 4
How to Toggle Mat-Expansion-Panel With Button Click
Angular:Failed to Load Images: 404 (Not Found)