Reputation: 3817
I have a INPUT BUTTON and INPUT FILE, I want to click the BUTTON and it will trigger the INPUT FILE event in REACT JS.
React.createElement('input',{type:'file', name:'myfile'})
then the button
React.createElement('a',{onClick: this.doClick},'Select File')
So how to define and trigger the INPUT FILE click event when we click the A HREF?
Your help is appreciate. :-)
Upvotes: 34
Views: 56015
Reputation: 31
For those who want to implement Farid's answer in Typescript, can do the following:
import React, {useRef} from 'react';
const FancyInput = () => {
const fileInput = useRef<HTMLInputElement>(null)
const handleClick = () => {
if(fileInput.current) {
fileInput.current.click()
}
}
const handleFileChange = event => {
console.log("Make something")
}
return(
<div className="patientactions-container">
<input
type="file"
onChange={(e) => handleFileChange(e)}
ref={fileInput}
/>
<div onClick={() => handleClick()}></div>
</div>
)
}
export default FancyInput;
Upvotes: 3
Reputation: 147
Anyone Looking for a Simple approach try this.
<div>
<input type="file" name="library-images" id="library-images" hidden />
<Button type='button' onClick={()=>{
document.getElementById("library-images")?.click()
}}>Upload</Button>
</div>
Upvotes: 2
Reputation: 21
const CustomInput = () => {
const handleClick = () => {
document.getElementById("file_upload").click();
};
const handleFileChange = (event) => {
console.log("Make something");
};
return (
<div className="patientactions-container">
<input type="file" id="file_upload" onChange={(e) => handleFileChange(e)} />
<div onClick={() => handleClick()}></div>
</div>
);
};
export default CustomInput;
Upvotes: 0
Reputation: 1722
Update: Sep 18, 2021
Note: On NextJS, I was facing onChange
event is not trigged from input file element. For that, we can use onInputCapture
or onChangeCapture
. For more detailed information, Stackoverflow - onChange event is not firing
Basic example on onChangeCapture
as per our requirement. Requires React ^16.8,
const Dummy = () => {
const inputFileRef = React.useRef();
const onFileChangeCapture = ( e: React.ChangeEvent<HTMLInputElement> ) {
/*Selected files data can be collected here.*/
console.log(e.target.files);
};
const onBtnClick = () => {
/*Collecting node-element and performing click*/
inputFileRef.current.click();
};
return (
<form>
<input
type="file"
ref={inputFileRef}
onChangeCapture={onFileChangeCapture}
/>
<button onClick={onBtnClick}>Select file</button>
</form>
);
};
Using useRef Hook in functional components. Requires React ^16.8,
const Dummy = () => {
const inputFileRef = useRef( null );
const onFilechange = ( e ) => {
/*Selected files data can be collected here.*/
console.log( e.target.files );
}
const onBtnClick = () => {
/*Collecting node-element and performing click*/
inputFileRef.current.click();
}
return (
<form className="some-container">
<input
type="file"
ref={inputFileRef}
onChange={onFileChange}
/>
<button onClick={onBtnClick}>Select file</button>
</form>
)
}
Class Implementation with React.createRef() and handling click with node element.
class Dummy extends React.Component {
constructor( props ) {
super( props );
this.inputFileRef = React.createRef();
this.onFileChange = this.handleFileChange.bind( this );
this.onBtnClick = this.handleBtnClick.bind( this );
}
handleFileChange( e ) {
/*Selected files data can be collected here.*/
console.log( e.target.files );
}
handleBtnClick() {
/*Collecting node-element and performing click*/
this.inputFileRef.current.click();
}
render() {
return (
<form className="some-container">
<input
type="file"
ref={this.inputFileRef}
onChange={this.onFileChange}
/>
<button onClick={this.onBtnClick}>Select file</button>
</form>
)
}
}
Upvotes: 66
Reputation: 7045
EDIT: This is a question I answered a long time ago not knowing very much react at this time. The fun thing is that it has been considered valid ^^.
So for anyone reading this answer; this answer is wrong and is a very good example of something you shouldn't do in react.
Please find below a nice anti-pattern, again, don't do it.
=================================================
You can achieve this using jQuery:
this.doClick: function() {
$('input[type=file]').trigger('click');
}
React does not provide specific functions to trigger events, you can use jQuery or simply native Javascript: see Creating and triggering events on MDN
Upvotes: -24
Reputation: 13155
Building on the answer from @YÒGÎ , here is an implementation using TypeScript:
class Dummy extends React.Component {
fileInputRef: React.RefObject<HTMLInputElement> = React.createRef();
forwardClickToInputElement = () => {
this.fileInputRef.current!.click();
};
handleUploadDemand = (ie: ChangeEvent<HTMLInputElement>) => {
const fileList: FileList = ie.target.files;
// do something with the FileList, for example:
const fileReader = new FileReader();
fileReader.onload = () => {
const str = String(fileReader.result);
try {
const parsedContent = YOUR_OWN_PARSING(str);
} catch (error) {
// YOUR OWN ERROR HANDLING
}
};
fileReader.readAsBinaryString(fileList[0])
}
render() {
return (
<div className="some-container">
<button onClick={this.forwardClickToInputElement}>Select File</button>
<input ref={this.fileInputRef} type="file" onChange={this.handleSelectFile} hidden={true}/>
</div>
)
}
}
References:
Upvotes: 4
Reputation: 136
Using Hooks with useref:
import React, {useRef} from 'react';
const FancyInput = () => {
const fileInput = useRef(null)
const handleClick = () => {
fileInput.current.click()
}
const handleFileChange = event => {
console.log("Make something")
}
return(
<div className="patientactions-container">
<input
type="file"
onChange={(e) => handleFileChange(e)}
ref={fileInput}
/>
<div onClick={() => handleClick()}></div>
</div>
)
}
export default FancyInput;
Upvotes: 7
Reputation: 411
You could trigger the input type file with ref, f.e:
on your class component:
<input
ref={fileInput => this.fileInput = fileInput}
type="file"
/>
<button onClick={this.triggerInputFile}> Select File </button>
and make a function on that class component too:
triggerInputFile = () => this.fileInput.click()
Upvotes: 35
Reputation: 1808
You don't need jQuery for this. You don't even need an event handler. HTML has a specific element for this, called label.
First, make sure your input
element has an id
attribute:
React.createElement('input',{type:'file', name:'myfile', id:'myfile'})
Then, instead of:
React.createElement('a',{onClick: this.doClick},'Select File')
Try:
React.createElement('label',{htmlFor: 'myfile'},'Select File')
(Instead of adding htmlFor
and id
attributes, another solution is to make the input
element a child of the label
.)
Now clicking the label
should trigger the same behaviour as clicking the input
itself.
Upvotes: 40