Input onChange is not working using ref value - javascript

I have a code for uploading excel file by clicking a button. So when I select a file by clicking button and again reselect same file by clicking, the onChange() event is not recognizing it.
My reference value :
this.inputFile = React.createRef(null)
My Upload Button :
<input
style={{ display: "none" }}
ref={this.inputFile}
onChange={this.onFileChange}
type="file"
accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,
application/vnd.ms-excel"
/>
<div className="btn btn-success btn-sm" onClick={this.onButtonClick} >
Upload File
</div>
My two onChange and onClick methods :
onFileChange =(e)=> {
this.setState({
selectedFile:e.target.files[0],
})
};
onButtonClick = () => {
this.inputFile.current.click();
};

If you select the same file, onchange event won't re-trigger. But if you insist on doing it, you need to remove the current value of the input on each click:
<input
style={{ display: "none" }}
ref={this.inputFile}
onChange={this.onFileChange}
type="file"
accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,
application/vnd.ms-excel"
onClick={this.clearFileInput} // ADD HERE
/>
<div className="btn btn-success btn-sm" onClick={this.onButtonClick} >
Upload File
</div>
clearFileInput = () => {
this.inputFile.current.value = null;
}

Related

htmlFor for input files label display

I was trying to set custom display for input type=file , but htmlFor with selecting id is not working .
By default input type=file displays as
Choose file(as button) - no file selected
I am trying to change those names "Choose files" and "no file selected" to my custom display , how can i achieve this ? I trying htmlFor with selecting id of the input field , but did not work out . I tried using label attribute but the text is being places on top of "Choose file" button.
Here's my tryout so far :
<label className="form-label" htmlFor='input-file'> select.....</label>
<input
className="form-control form-control-lg form-control-solid"
type="file"
id="input-file"
name="thumbnailImg"
value={undefined}
onChange={(e) => file_choosen(e)}
/>
The output is like :
select...
[Choose File] [no file selected]
I am trying to display something like :
[select...] [***custom no file selected here***]
If you do not wish to use the default input element then you need to:
Hide the input element
Use a button that you can style to your wishes
On click then trigger the input file click
import { useRef, useState } from "react";
export default function App() {
const ref = useRef();
const [file, setFile] = useState(null);
function file_chosen() {
setFile(ref.current.files[0]);
}
return (
<div>
<div style={{ display: "flex", flexDirection: "row", gap: 4 }}>
<button onClick={() => ref.current.click()}>Select file</button>
<p>{file === null ? "No file chosen" : "1 file selected"}</p>
</div>
<input
onChange={file_chosen}
ref={ref}
type="file"
style={{ display: "none" }}
/>
</div>
);
}
codesandbox example

How to forward input ref to a function by onClick button

I am trying to forward input ref text/string data to a function by clicking the button. but I cant forward or pass the data to my function by using button
--questionRef is my ref input data
--answerQuestion is my function
<input ref={questionRef} size="80"></input>
<button type="button" onClick={answerQuestion} >Enter</button>
I tried to use my button for forward the questionRef input to answerQuestion function but it failed. Also it works when I click enter on my keyboard
Pretty simply:
<input ref={questionRef} size="80"></input>
<button
type="button"
onClick={() => answerQuestion(questionRef)}
>Enter
</button>
Eventually, you can include also the onClick event to your function, depends on what you need to do with it:
<input ref={questionRef} size="80"></input>
<button
type="button"
onClick={(e) => answerQuestion(questionRef, e)}
>
Enter
</button>
Based on Junius L. comment:
const questionRef = useRef()
const answerQuestion = () => {
doSomethingWithRef(questionRef) // questionRef is accessible in whole component scope
}
<input ref={questionRef} size="80"></input>
<button
type="button"
onClick={answerQuestion}
>Enter
</button>

Input element of type="file" not activated after click event

When I click on the SELECT A FILE button on my UI, it does not allow me to upload a file as I expect it to.
Can someone help me figure out what is going wrong?
Here is the HTML portion of the button:
<div style="padding-bottom: 15px">
<input type="file" id="input-file" hidden="hidden">
<button type="button" id="select-a-file-custom-button">SELECT A FILE</button>
<span id="custom-text">No file chosen yet!</span>
</div>
Here is the JavaScript that is meant to activate the button:
// Step 1: Load file
selectFileBtnCtm.addEventListener("click", () => {
selectFileBtn.click();
});
selectFileBtn.addEventListener('change', e => {
selectFileBtnCtm.innerHTML = "FILE LOADED"
customTxt.innerHTML = e.target.value;
hashBtnTxt.innerHTML = "Ready to hash!";
hashBtn.id = 'custom-button';
});
In case you need to see all files in the directory, click here.

Add 'keydown' event listener to document except for input field

I am creating a Hangman game with a virtual keypad and a form input section where users can guess the entire word.
I am able to add a 'keydown' event listener to the document, but I DO NOT want want the 'keydown' event to fire off if I am typing into the input field.
Here is how I've added the event listener.
document.addEventListener('keydown', handleKeyDown);
Here is the form input.
<form onSubmit={e => onSubmit(e)}>
<div className="input-group">
<input
type="text"
className="form-control"
name="letter"
placeholder="Guess the word"
value={formWord}
onChange={e => setFormWord(e.target.value.toUpperCase())}
disabled={disabled}
/>
<div className="input-group-append">
<button
className="btn text-white"
type="submit"
disabled={disabled}
>
<i className="far fa-arrow-alt-circle-right" /> Go!
</button>
</div>
</div>
</form>
I've already tried using document.getElementsByTagName[0].removeEventListener('keydown', handleKeyDown), but that's not working. I'm assuming that's because the event listener was added onto the actual document instead of the element.
Please help!
Inside handleKeyDown, only execute the body of the function if the event.target does not match the input field, eg:
const handleKeyDown = (event) => {
if (event.target.matches('[name="letter"]')) {
return;
}
// rest of function body
};

react - how to show relevant element when click button

I have component that renders jsx like this
<section>
<div>
<input type="text" class="hide" />
<button id={item.uniqueID}>show input</button>
</div>
<div>
<input type="text" class="hide" />
<button id={item.uniqueID}>show input</button>
</div>
<div>
<input type="text" class="hide" />
<button id={item.uniqueID}>show input</button>
</div>
</section>
I want this behavior, when I click the button in the first div, the input in the first div will show. Similarly, I click the button in the third div the input in third div will show.
How you do that in react?
If it were me I would make a new component out of:
show input
Lets call it <InputToggler/>
and then it would have a state of inputHidden for its own input and use classes to determine if it should show or not and the button would have an onclick handler to toggle the state of hidden or shown. Here is a pen showing exactly that
http://codepen.io/finalfreq/pen/VKPXoN
class InputToggler extends React.Component {
constructor() {
super();
this.state = {
inputHidden: true
}
}
toggleInput = () => {
this.setState({
inputHidden: !this.state.inputHidden
})
};
render() {
const inputClass = this.state.inputHidden ? 'hide' : '';
const buttonLabel = this.state.inputHidden ? 'show input' : 'hide input'
return (
<span>
<input type="text" className={inputClass} />
<button onClick={this.toggleInput} id={this.props.item.uniqueID}>
{buttonLabel}
</button>
</span>
)
}
}
This is the concept not the exact code.
Each button should have onClick with callback to a function ex. toggleShow
<button id={item.uniqueID} onClick={this.toggleShow.bind(this)}>show input</button>
toggleShow do something like:
toggleShow(e){
var item = e.target.id;
this.setState({inputClassName1: "hide"})
at the same time the input field classname should refer to the state
Note that I omitted the fact that you have multiple objects, you may want to handle their references in arrays.

Categories