Updating a React Input text field with the value on onBlur event - javascript

I have the following input field as below. On blur, the function calls a service to update the input value to the server, and once that's complete, it updates the input field.
How can I make it work? I can understand why it's not letting me change the fields but what can I do to make it work?
I can't use the defaultValue because I will be changing these fields to some other ones
<input value={this.props.inputValue} onBlur={this.props.actions.updateInput} />

In order to have the input value editable you need to have an onChange handler for it that updates the value. and since you want to call a function onBlur, you have to bind that like onBlur={() => this.props.actions.updateInput()}
componentDidMount() {
this.setState({inputValue: this.props.inputValue});
}
handleChange = (e) => {
this.setState({inputValue: e.target.value});
}
<input value={this.state.inputValue} onChange={this.handlechange} onBlur={() => this.props.actions.updateInput(this.state.inputValue)} />

Ways of doing this:
Do not assign value property to input field, whenever onblur method gets trigger, hit the api like this:
<input placeholder='abc' onBlur={(e)=>this.props.actions.updateInput(e.target.value)} />
Update value to server:
updateInput(value){
/*update the value to server*/
}
If you are assigning the value property to input field by this.props.inputValue, then use onChange method, pass the value back to parent component, change the inputValue by using setState in parent, it will work like this:
<input value={this.props.inputValue} onChange={(e)=>this.props.onChange(e.target.value)} onBlur={()=>this.props.actions.updateInput} />
In Parent Component:
onChange(value){
this.setState({inputvalue:value});
}
Update value to server:
updateInput(value){
/*update the value to server*/
}

You will want to bind a onChange event to update your state. Make sure to use the bind method in your constructor so that you do not lose the 'this' context within your onChange event handler method. You will then want to pass the value back to your update input method onBlur. Something like this:
constructor(props) {
super(props);
this.state = {
inputValue: props.inputValue
};
this.handleChange = this.handleChange.bind(this);
};
handleChange = (e) => {
this.setState({inputValue: e.target.value});
}
<input
value={this.state.inputValue}
onChange={this.handleChange}
onBlur={() => this.props.actions.updateInput(this.state.inputValue)}
/>

Related

"Reset" button won't work unless it refreshes page, and gives me an error otherwise (React.JS)

So I'm working in React.JS, and I'm trying to make something like an input field, where a user can enter a number of their choice, and it will show up in the text.
I decided to add a "Reset to zero" button, as an extension.
<div>
Count: {this.state.value}
<form>
<input type="number" value = {this.state.value} onChange = {this.inputChange}/>
<br/>
<button onClick = {this.reset}>reset to zero</button>
</form>
</div>
It works, but it refreshes the page every time it does so.
I read online, and I decided to add "type=button" to my button as so:
<button type="button" onClick = {this.reset}>reset to zero</button>
When I run my code again, it still increments fine, but when I click the button, nothing happens, and when I try to increment it again, I get an error, "TypeError: this.setState is not a function".
The error is coming from this method:
inputChange = event => {
this.setState ({value: event.target.value})
}
I know where the error is coming from, but I don't know why it happened, or how to fix it (note that I'm also a beginner at JavaScript and React.JS)
I hope someone can help me.
Here's my code in entirety, for reference.
class Slider extends React.Component {
constructor(props){
super(props);
this.state = {
value: 0
}
}
inputChange = event => {
this.setState ({value: event.target.value})
}
reset = () => {
this.setState = ({
count: 0
})
}
render() {
return (
<div>
Count: {this.state.value}
<form>
<input type="number" value = {this.state.value} onChange = {this.inputChange}/>
<br/>
<button type = "button"onClick = {this.reset}>reset to zero</button>
</form>
</div>
);
}
}
Thank you guys, in advance.
The reason nothing happens on reset and you are getting that error on input change, is that you are reassigning this.setState in your reset function rather than calling it. Also, you are setting count instead of value, which would lead to the wrong state being set.
This is what your reset function should be:
reset = () => {
this.setState ({
value: 0
})
}
When you call this.setState, React will trigger a re-render in your component with the new state.
That is currently not happening when you click reset. On your subsequent call to inputChange, this.setState has been reassigned with an object, and is no longer callable, throwing that error.
Try replacing your button like this:
<button type = "button"onClick = {this.reset.bind(this)}>reset to zero</button>
This will force the method to execute being this the scope.

Focusing input field with Mousetrap.js - but input field also pastes the hotkey as value?

Have a look at the following example. I have enhanced the official example here with some Mousetrap functionality. So whenever somebody presses alt+1, the first input field will focus, whenever somebody presses alt+2 the second input field will be focused. It works.
Problem:
However, the input field then also takes the value of whatever was pressed as the hotkey (alt+1 then renders to ¡, alt+2 renders to € in the input). But I just want this to be a hotkey, I don't want it's actual value in the input field. How do I do this?
I could clear / delete the input field completely. This would work in the example here, but I don't want to do it since in my final app the state of the input field will need to be preserved, so I cannot just delete it.
Any advice?
import React from "react"
import Mousetrap from "mousetrap"
export default class CustomTextInput extends React.Component {
constructor(props) {
super(props)
// create a ref to store the textInput DOM element
this.textInput = React.createRef()
this.textInput2 = React.createRef()
this.focusTextInput = this.focusTextInput.bind(this)
}
componentDidMount() {
Mousetrap.bind("alt+1", () => {
this.focusTextInput(1)
})
Mousetrap.bind("alt+2", () => {
this.focusTextInput(2)
})
}
focusTextInput(id) {
// Explicitly focus the text input using the raw DOM API
// Note: we're accessing "current" to get the DOM node
if (id === 1) {
this.textInput.current.focus()
}
if (id === 2) {
this.textInput2.current.focus()
}
}
render() {
// tell React that we want to associate the <input> ref
// with the `textInput` that we created in the constructor
return (
<div>
<input type="text" ref={this.textInput} className="mousetrap" />
<input type="text" ref={this.textInput2} className="mousetrap" />
</div>
)
}
}
I
have you tried event.preventDefault() ?
Mousetrap.bind("alt+1", (e) => {
e.preventDefault();
this.focusTextInput(1);
})
Mousetrap.bind("alt+2", () => {
e.preventDefault();
this.focusTextInput(2)
})
#Dhananjai Pai solution didn't worked for me in the same case.
I know this is very old question, so I will just leave the solution, that worked for me, just if someone needs it.
<input
type="text"
placeholder="Put focus here"
name="something"
id="order-code"
class="form-control barcodeScanner"
>
if (typeof Mousetrap !== 'undefined') {
Mousetrap.bind(['`', '('], function (e) {
e.preventDefault();
$('.barcodeScanner').focus()
}, 'keyup');
}
Adding as third option the 'keyup' event solved the issue with typing inside the input.
Source:
https://craig.is/killing/mice#api.bind
There is a third argument you can use to specify the type of event to listen for. It can be keypress, keydown or keyup.
It is recommended that you leave this argument out if you are unsure. Mousetrap will look at the keys you are binding and determine whether it should default to keypress or keydown.

Update values in input onkeypress in ReactJS

I have been trying to get how to update an input based on keypress in window with ReactJS. I'm building a basic calculator, and it has only one input. I want the input to always be targeted once a key is pressed and also update the values. I also have another function for validation, so the keypress function will still pass through the validation function. Thank you!
I have something like this:
window.onkeypress = function(e){
this.inputFocus(); //my custom function to position the cursor in the input
this.setState({display: this.state.display + e.key});
}
I just don't know the proper location to fit it in cos it says syntax error: unexpected token, pointing at the "." between "window" and "onkeypress"
If you have focus on the input field, by pressing a button, it should enter the value into that input field, and so all you should need to do is make your input a controlled component by doing the following
export default class YourClass extends Component {
constructor(props) {
super(props);
this.state = {
numberValue: 0
}
}
updateValue = (numberValue) => {
this.setState({numberValue})
}
render() {
return (
<input
type='number'
value={this.state.numberValue} // this is initialized in this.state inside the constructor
onChange={(input) => this.updateValue(input.target.value)}
/>
)
}
}
So whenever you change the value, it will automatically update the state, which then sets the value of your input. This is all predicated on you having focus on that input though, so make sure it has focus.
You can assign focus by referencing the element through javascript like...
document.getElementById('yourElement').focus()
OK here it is... I called the window.onkeydown function outside the class as it doesn't update any state. And I later realised that window.onkeydown targets and add the values in the input
import ... from ...;
window.onkeydown = function(e) {
input.focus()
}
class App extends ... {
...
}
export default App;

react - setting input prop based on input name

I have a checkbox input:
import { Checkbox } from 'semantic-ui-react';
<Checkbox
checked={false}
ref={id}
/>
Now I would like to write a function that set this checkbox's checked to true (the onClick function goes on another React element, not the checkbox itself):
onClick: (id) => {
//Find the correct checkbox, set the prop
this.refs[id].checked = true;
}
But I have no idea how to do it (the above code does nothing). How do I find react components based on a certain prop?
Maintain a state object that has mapping of id to checkbox state and then onClick based on the id change the state
this.state = {
checked: {'12': true. '23':false}
}
<Checkbox
checked={this.state.checked[id]}
/>
If you want to toggle
onClick = (id) => {
var checked = {...this.state.checked}
checked[id] = !this.state.checked[id];
this.setState({checked})
}
If you only want to set
onClick = (id) => {
var checked = {...this.state.checked}
checked[id] = true;
this.setState({checked})
}
You have to add an onClick attribute in the Checkbox and the funciton name.
Inside the on click function you should get as parameter the event
and check the evet.target.checked
which is the checkbox's attribute to show clicked status.
You don't need to use refs if its all in the same component.
Let me know if you have trouble
You could do something like:
<Checkbox
checked={false}
ref={id}
onClick={() => { this.onClick(id); }}
/>
Not sure if this Checkbox is rendered in the same component tho, so the reference to this might be wrong.
onClick: (id) => {
this.refs[id].checked = true;
}

When to bind this keyword to an event handler in react?

So, let's say I have a class named Search that is a simple input field with a submit button. Here's the code for that.
class Search extends Component {
constructor(props){
super(props);
this.state = {term: ''};
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
console.log(this);
console.log(e.target.value);
this.setState({term: e.target.value});
}
render() {
return (
<form className='input-group'>
<input className='form-control'
placeholder='City'
onChange={this.handleChange}
value={this.state.value}/>
<span className='input-group-btn'>
<button type='submit' className='btn btn-primary'>Submit</button>
</span>
</form>
)
}
}
So, I need to bind the this keyword to the event handler, handleChange, inside the constructor of the class so that it has the correct reference to this inside the handleChange event handler.
However, if I change the code to the following
class Search extends Component {
constructor(props){
super(props);
this.state = {term: ''};
//this.handleChange = this.handleChange.bind(this);
Line comment above
}
handleChange(e) {
console.log(this);
console.log(e.target.value);
this.setState({term: e.target.value});
}
render() {
return (
<form className='input-group'>
<input className='form-control'
placeholder='City'
onChange={(e) => this.handleChange(e)}
Line change above
value={this.state.value}/>
<span className='input-group-btn'>
<button type='submit' className='btn btn-primary'>Submit</button>
</span>
</form>
)
}
}
Now, if I change the code to the above, I no longer need to do that because I am calling this.handleChange from inside of a callback. Why is this the case?
The reason is that you use an arrow function when you create the callback.
You don't need to bind arrow functions to this, because arrow functions "lexically binds the this value".
If you want, you can change your event handler functions into arrow functions, so that you don't need to bind them. You may need to add the babel plugin 'transform-class-properties' to transpile classes with arrow functions.
If you want to change handleChange into an arrow function, simply change
handleChange(e) {
...
}
to
handleChange = (e) => {
...
}
What you have to consider is what you are expectingthis will evaluate to inside a method and this is something that is not just confined to callbacks.
In the the case of your handleChange method you are referring to this.setState where you are expecting this to be the body of your containing class where it is defined when you create a class extending from React.Component.
When a DOM on-event handler like onClick is invoked, the this keyword inside the handler is set to the DOM element on which it was invoked from. See: Event handlers and this on in-line handler.
As you can infer, there is no setState method on a DOM element, so in order to achieve the desired result, binding the this to the correct scope/context is necessary.
This can be achieved with .bind() or the => (arrow function), the latter of which does not define its own its own scope/context and uses the scope/context it is enclosed in.
Like I said previously the redefining of this is not just confined to DOM on-event callbacks. Another example is when you call the .map() method where you can define the context of this by passing in a context value as a second argument.

Categories