React prevent form submission when enter is pressed
I have the following React Search Bar component where the parent container can call using
<SearchBar onInputChange={this.handleInputChange} />
Everytime the user changes the input, the parent container will be notified. This is why my search bar does not need any submit button.
However, I am finding that if I press enter inside my search bar, the whole page refreshes. And I dont want that.
I know if I have a button in the form, I could call event.preventDefault(). But in this case I have no button so I dont know what to do here
class SearchBar extends Component {
constructor(props) {
super(props);
this.state = { value: '' };
this.handleChange = this.handleChange.bind(this)
}
handleChange(e) {
this.setState({ value: e.target.value });
this.props.onInputChange(e.target.value);
}
render() {
return (
<div id="search-bar">
<form>
<FormGroup controlId="formBasicText">
<FormControl
type="text"
onChange={this.handleChange}
value={this.state.value}
placeholder="Enter Character Name"
/>
</FormGroup>
</form>
</div>
);
}
}
export default SearchBar
You need to create a form handler that would prevent the default form action.
The simplest implementation would be:
<form onSubmit={e => { e.preventDefault(); }}>
But ideally you create a dedicated handler for that:
<form onSubmit={this.submitHandler}>
with the following implementation
submitHandler(e) {
e.preventDefault();
}
In a React component with a Search input field, nested in a larger (non-React OR React) form, this worked best for me across browsers:
<MyInputWidget
label="Find"
placeholder="Search..."
onChange={this.search}
onKeyPress={(e) => { e.key === 'Enter' && e.preventDefault(); }}
value={this.state.searchText} />
(e)=>{e.target.keyCode === 13} (#DavidKamer's answer) is incorrect: You don't want the event.target. That's the input field. You want the event itself. And in React (specifically 16.8, at the moment), you want event.key (e.key, whatever you want to call it).
I'm not sure if this works for every situation, as when you press enter in a form's input field you will still trigger the onSubmit method, although the default submit won't occur. This means that you will still trigger your pseudo submit action that you've designed for your form. A one liner with ES6 that solves the problem specifically and entirely:
<input onKeyPress={(e)=>{e.target.keyCode === 13 && e.preventDefault();}} />
This solution should have 0 side effects and solves the problem directly.
The best way to prevent the ENTER, as suggested also by Eon is to add the following to your input element:
onKeyPress={(e) => { e.key === 'Enter' && e.preventDefault(); }}
This works for me:
<Input
...
onKeyDown={(e) => { e.key === 'Enter' && e.preventDefault() }}
/>
prevent for Enter key for search input:
<input type="text" onKeyPress={e => {
if (e.key === 'Enter') e.preventDefault();
}} />
Related
I need to know if I can verify if user pressed a key or not only with onchange event, because I get the text on input with a QR reader, but there also exists the possibility for the user to manually enter the data.
I have this code (example):
_getValue = (event) => {
let value = event.target.value;
}
render() {
<input type="text" onChange={this._getValue} />
}
So, on _getValue method, which is from an onchange event, I need to check if the change is coming from a key or from the QR reader.
Thank you to all!
You could use the keydown event.
You would probably end up with something like this
_getValue = (event) => {
let value = event.target.value;
}
const handleKeyPress = (e) => {
e.preventDefault();
return;
}
render() {
<input type="text" onChange={this._getValue} onKeyPress={handleKeyPress} />
}
You can read more on the event on MDN
I have a text input in my React app which I don't want to take inputs which are greater than 100. For example, If the entered value is 105, an alert is created and the event is terminated i.e changing input value is not gonna happen. Now I couldn't find a way to do this inside onChange function. Any help would be highly appreciated.
<input onChange={handleChange} name="t"/>
handleChange = e => {
if(e.target.value > 100){
alert("High")
//Here I want to stop event so that changing text in the input doesn't happen
}
}
Make it a controlled input and only set the value if a condition is met.
const App = () => {
const [value, setValue] = React.useState("");
const handler = (e) => {
const value = Number(e.target.value);
value <= 100 && setValue(value);
};
return (
<input onInput={handler} type="number" value={value} />
);
}
ReactDOM.render(<App/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
If I'm understanding you properly, if a specific condition is not met, you want to prevent the input from reflecting the text the user just entered.
In order to accomplish this, you'll need to control your input's value via state.
That means doing something like this:
<input onChange={handleChange} name="t" value={this.state.tInput}/>
handleChange = e => {
if(parseInt(e.target.value) > 100) {
alert("High")
// set input state here to previous value to re-render and remove unwanted input values from input
return this.setState(({tInput}) => ({tInput}))
}
return this.setState({tInput: e.target.value})
}
handleChange = e => {
if(e.target.value > 100){
alert("High");
e.target.value = "";
}
else {
// your normal processing
}
}
should work.
Explanation:
Your code would simply not be executed in case the if condition is true.
The line e.target.value = "" doesn't actually "not show" the users input (as asked for in comment), but rather overrides it with empty string.
Mention:
This solution has nothing to do with React, but rather works in any context.
Below is the part of the react component where a dynamic checkbox is listed:
<div className="pb-4">
<p>Choose the task owner(s):</p>
{
peerIds.map(id => {
if (currentUserId != id)
return (
<label className="checkbox-inline mr-3">
<input onChange={onChange_TaskOwner}
type="checkbox"
name="taskowner"
checked={st_taskOwnersId.filter(function (item) {return (item == id)}).length > 0}
value={peers[id].id} />
<span>{peers[id].fullName}</span>
</label>
)
})
}
<div style={{ clear: 'both' }}></div>
</div>
In the above code I set checked to false/true if the current id is already in the hook state object called st_taskOwnersId.
I store the Ids of the checked items using hook as below. onChange_TaskOwner function updates the st_taskOwnersId depending on whether it is checked or unchecked:
const [st_taskOwnersId, set_taskOwnersId] = useState([] as any);
const onChange_TaskOwner = (event) => {
event.preventDefault();
if (event.target.checked)
set_taskOwnersId([...st_taskOwnersId, event.target.value]);
else
set_taskOwnersId(st_taskOwnersId.filter(function (item) {
return (item != event.target.value);
}));
}
The code runs without errors. The only problem is I have to click twice to check/uncheck the check boxes. I have no clue why this is happening. Any help?
I believe the problem is on onChange_TaskOwner function. You should remove event.preventDefault(); call.
I tried to reproduce your component on this codepen, without the event.preventDefault(); works fine, if you add it, the same kind of error start happening.
I have been attempting to add several onKeyPress to existing onClick tags in my React.js project, more specifically, being able to press Enter to fire off an onClick after tabbing to a link. The onKeyPress in my code works properly when I insert a simple console.log() to test, however it fails when I insert the function. I left out irrelevant portions of code for brevity. Essentially I need click and Enter to do the same thing. Thanks!!!
class Link extends React.Component {
changeSection(e) {
// code to change section
}
render() {
return (
<div>
<a id="menu-item" tabIndex={this.props.tabIndex} onKeyPress={(e) => {(e.key === 'Enter' ? this.changeSection.bind(this) : null)}} onClick={this.changeSection.bind(this)}>
{this.props.linkText}
</a>
</div>
);
}
}
Another option would be to let the browser handle it for you, especially because you're already using an a tag. It might not be nice to add the href="#", but it's probably better than a function that is regenerated every render. Plus you don't have the overhead with the custom tabbing implementation.
Try it here:
class Link extends React.Component {
changeSection(e) {
e.preventDefault();
console.log('Fired!');
}
render() {
return (
<div>
<a
id="menu-item"
href="#"
onClick={this.changeSection.bind(this)}
>
{this.props.linkText}
</a>
</div>
);
}
}
ReactDOM.render(
<Link linkText="Test" />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
It looks like a syntax error. Does this work? If not, what error are you getting?
<a id="menu-item" tabIndex={this.props.tabIndex} onKeyPress={(e) => (e.key === 'Enter') ? this.changeSection.bind(this) : null} onClick={this.changeSection.bind(this)}>
You mixed 2 syntax together I think.
You can change this;
onKeyPress={(e) => {(e.key === 'Enter' ? this.changeSection.bind(this) : null)}}
With this;
onKeyPress={(e) => {
if(e.key === 'Enter') this.changeSection.bind(this);
else null
}}
or with this;
onKeyPress={(e) => (e.key === 'Enter' ? this.changeSection.bind(this) : null)}
onKeyPress={(e) => {(e.key === 'Enter' ? this.changeSection.bind(this) : null)}}
I think this is where you fail. Your code here just binds new context to a function but doesn't call it.
I'm very new to ReactJS and I'm just trying to do some small things to understand more.
I was wondering if the OnKeyPress can trigger a button press. I've seen a few similar questions but what the OnKeyPress triggered was just a console.log or an alert. So I wasn't sure how to trigger the button press.
This is what I have so far:
class Form extends React.Component {
onButtonPress = (e) => {
// this is just an example of what happens when the button is pressed.
this.setState({isClicked: true});
}
keyPress = (event) => {
if (event.key == 'Enter'){
// How would I trigger the button that is in the render? I have this so far.
this.onButtonPress();
}
}
render() {
return (
<div>
<div className="fieldForm">
<input
value={name}
type="name"
onKeyPress={this.keyPress}
/>
</div>
<Button onClick={this.onButtonPress}>Submit</Button>
</div>
)
}
}
Please note that I didn't include everything in here such as the constructor, props, or the state object attributes.
The purpose of this is to make it look like the button has been clicked. When the button is clicked, it'll show a small loading sign on the button. I want the same thing to happen if I were to press enter (with the loading sign on the button, that's why I want the button pressed).
Is this possible?
Programmatically triggering DOM events is not something you should do unless you have very specific needs.
Both onKeyPress and onClick are event handlers, you can do anything you want when an event happens. I would just call a function that sets the state you want from both handlers.
Here's an example:
class Form extends React.Component {
handleFormSubmit = () => {
this.setState({ isClicked: true });
};
handleButtonPress = () => {
this.handleFormSubmit();
};
handleKeyPress = event => {
if (event.key == 'Enter') {
this.handleFormSubmit();
}
};
render() {
return (
<div>
<div className="fieldForm">
<input value={name} type="name" onKeyPress={this.handleKeyPress} />
</div>
<Button onClick={this.handleButtonPress} loading={this.state.Load}>
Submit
</Button>
</div>
);
}
}
In case you have no other way and you should click on this element for some vague reason and the method that elas said didn't work for you. try this:
onButtonPress = (e) => {
console.log('hi hi')
}
handleKeyPress = (event) => {
if (event.key === 'Enter') {
this.refs.but.click()
}
}
render () {
return (
<Layout>
<div>
<div className="fieldForm">
<input
value={'name'}
type="name"
onKeyPress={(e) => this.handleKeyPress(e)}
/>
</div>
<Button onClick={this.onButtonPress} ref="but">Submit</Button>
</div>
</Layout>
)
}