I have a React Bootstrap Form component
https://react-bootstrap.github.io/components/forms/#forms
I just need to be able to get the name/ref of the input box that the user is typing inside so I can update the state dynamically. I did this already with the standard Form using:
this.setState({
[event.target.name]: event.target.value
})
but I wanted to use React's Bootstrap form. I can already get the value of the Form input, but I can't find a way to get its reference name (like if the input box is for dealerName, I am unable to get the string 'dealerName' so I can update it dynamically instead of having to hardcode the state property name to a value to update it) so I can dynamically update the state. Without that, I would have to create multiple separate functions for all the different forms I have.
This is my sample React Bootstrap Form:
<Form>
<Form.Group controlId="formDealersAdd">
<Form.Label>userId:</Form.Label>
<Form.Control type="text" placeholder="userId" ref={this.userId} onChange={this.handleInputChange}/>
<Form.Label>dealerName:</Form.Label>
<Form.Control type="text" placeholder="dealerName" ref={this.dealerName} onChange={this.handleInputChange} />
<Form.Label>dealer id:</Form.Label>
<Form.Control type="text" placeholder={did} ref={this.did} onChange={this.handleInputChange} />
<Button variant="secondary" size="lg" onClick={this.handleDealersAddFormClick}>SUBMIT</Button>{' '}
</Form.Group>
</Form>
My constructor looks like this:
class App extends Component {
constructor(props) {
super(props);
this.userId= React.createRef();
this.dealerName = React.createRef();
this.did = React.createRef();
this.state = {
userId: '',
dealerName: '',
did: '',
};
}
}
And my handleInputChange function:
handleInputChange = (event) => {
event.preventDefault()
// manually hardcoding it like this causes issues and makes my code bad
this.setState({
userId: this.userId.current.value,
dealerName: this.dealerName.current.value,
did: this.did.current.value
})
}
I was originally handling the inputChange by simply setting the state with
this.setState({
[event.target.name]: event.target.value
})
and this worked fine for the standard Form (non-React Boostrap form) and it does return the correct value for the input that is being actively updated/being typed inside by a user, but event.target.name does not work.
Thus, as you can see above, I just manually hardcoded the values to be updated inside the state object, but this is messy and causes error when the user clicks to see a new Form on my website and the properties are null and the state tries to update so it crashes.
Is there a way to update my state properties for the inputs of the React Bootstrap form similar to how I used [event.target.name] : event.target.value for the regular Form?
To get its reference name, add values to the props name would be fine
Before:
<Form.Control type="text" placeholder="userId" ref={this.userId} onChange={this.handleInputChange}/>
After:
<Form.Control type="text" name="userId" placeholder="userId" ref={this.userId} onChange={this.handleInputChange}/>
Related
I am using React with Material UI's Textfield components. Was trying to find out the best way to set the form states with the least redundancy. Like for example, I have 8 different input fields. Instead of having a seperate handler for each input, like for example handleFirstName, handleLastName, handleEmail, handleInfo, etc.
So to accomplish this, I tried to create a handleChange handler which looks like below:
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.value
});
}
And on each component,
<TextField
className={classes.formInput}
name="firstName"
onChange={e => this.handleChange(e.target.value)}
required
id=""
type="text"
InputLabelProps={{
shrink: true,
}}
error={!firstName}
helperText="Name is required"
label="First Name"
variant="standard" />
<TextField
className={classes.formInput}
name="lastName"
onChange={e => this.handleChange(e.target.value)}
required
id=""
type="text"
InputLabelProps={{
shrink: true,
}}
label="Last Name"
variant="standard" />
And here is my state object
constructor(props) {
super(props);
this.state = {
firstName: '',
lastName: '',
...,
};
}
These are just two of the input fields, but there are about 6 more fields that look the same. Any idea to combat this undefined name?
The problem is that you are not passing the complete event object. You are passing only the value. That is the reason why you are getting the name as undefined.
Try changing the onChange event to below -
onChange={this.handleChange}
This way you will get the complete event object in the function's e variable.
I think you need to handle multiple input field changes in single function.It is doable. try this
handleChange = (e)=>{
{name,value} = e.target;
this.setState({
[name]=value;
});
}
finally when to pass the onChange method to fields use :
onChange = {this.handleChange}
I have a list and edit button when user click edit button opening a new modal. I want to auto populate the selected username mail etc. Server side response is {this.test.name} i give him to input value to auto populate but when user click edit button ı can see the name but ı couldnt change the input how do ı do that ?
Code :
<div className = "form__group field">
<input type="input" className="form__field" placeholder="Name" name="name" id="name" value={this.test.name} />
<label htmlFor="name" className="form__label">Adı-Soyadı</label>
</div>
You cannot change that input value because you've set the value to this.test.name and did not defined an onChange handler. So what you should do is create a state for your input field and on componentDidMount, populate this state with data from server.
Then on your input field
this.state = {
val: ''
}
<input value={this.test.name} onChange={e => setState({val: e.target.value})}/>
Maybe there can be a syntax error, because I am used to work with hooks now, but that's pretty much the gist of it
Keep the name in the state:
this.state = {
name: '',
}
(setState when you have it, if you retrieve it only on mount)
Pass value={this.state.name} to the input.
Pass onChange={handleNameChange} to the input.
const handeNameChange = (e) => {
setState({ name: e.target.value });
}
If you are using hooks, you could do something like this:
import { useState } from "react"; // import useState
export default function App() {
const [name, setName] = useState(""); // useState hook
// handle change event
const handleChange = (e) => {
e.preventDefault(); // prevent the default action
setName(e.target.value); // set name to e.target.value (event)
};
// render
return (
<div>
<input value={name} type="text" onChange={handleChange}></input>
<p>{name}</p>
</div>
);
}
First, we import the useState() hook to be able to use it, then we use it to store the state for the name value, you can give it an initial value of an empty string (""). In the handleChange() function, we prevent the default action and set the state to e.target.value, this is the input value passed by the event (as (e)). Every time the input changes, the state will update and the page will re-render.
You could check out my sandbox here
I have a form loaded with certain values in in its field. I'm unable to type in the value of fields or delete the existing default values when the form was rendered. Basically, I'm trying to add an Update operation in my form in which values are shown in field (e.g. On clicking an edit button, form is displayed with the values).
I tried to capture the event with onChange method but it's not working as I expected.
The default values are fetched as props from its parent and passed to the value argument of the form. I'm using semantic UI React components for the form.
Here is the example in codesandBox of what I'm trying to implement:
codesandbox
In the above example, variable is passed to value in form.
if you look at the error, it clearly says: A component is changing an uncontrolled input of type text to be controlled. Which means you have to store the values of name, email in state on initialization, and have those values changed on onChange event. And not update values only on onChange.
import React, { Component } from "react";
import { Form } from "semantic-ui-react";
class FormExampleClearOnSubmit extends Component {
state = {
name: "james",
email: ""
};
handleChange = (e, { name, value }) => this.setState({ [name]: value });
handleSubmit = () => this.setState({ email: "", name: "" });
render() {
const { name, email } = this.state;
return (
<Form onSubmit={this.handleSubmit}>
<Form.Group>
<Form.Input
placeholder="Name"
name="name"
value={name}
onChange={this.handleChange}
/>
<Form.Input
placeholder="Email"
name="email"
value={email}
onChange={this.handleChange}
/>
<Form.Button content="Submit" />
</Form.Group>
</Form>
);
}
}
export default FormExampleClearOnSubmit;
I am trying to type and save data from a input field in a Modal. For some reason I cant type inside the field once I render the modal.
This is my code:
constructor(props){
super(props);
this.state = {
showHide : false,
email: ' '
}
}
handleChange = (e) => {
this.setState({
[e.target.email]: e.target.value
})
}
This is where I attempted to have the user input.
<FormGroup>
<label for="message-text" class="col-form-label">Email Adress:</label>
<input type="text" class="form-control" name='email' placeholder="Email"
value={this.state.email} onChange={e => this.handleChange(e)} >
</input>
</FormGroup>
Any ideas on why I cant type inside the the field? Please and thank you.
So the mistake is within your setState, you have to use e.target.name. This name property will provide a string value 'email' as set in input.
Description:
Name is an HTML attribute that is accessible from Event object being passed into the function, this name is set as 'email' in your input as you can see. And since you are not updating the state correctly, that input which is right now a controlled component (value bound to state) isn't being updated.
For more details look into ES6 computed names properties.
this.setState({
[e.target.name]: e.target.value
})
I am using reactjs controlled input
reference for below code
<input type="text"
value={this.state.username}
onChange={(e) => this.setState({ username: e.target.value })}
/>
I want to avoid extra code like value , onChange And move them to component like
<input type="text" setValueOnChange=(this,'username')/>
While getting exactly the result you want is not possible, just because it is not a syntactically valid JSX. It is possible to make something looking quite similar to that:
// in render
<input type="text"
value={this.state.username}
onChange={setValue(this, 'username')}
/>
// add this method to the component
setValue(propName) {
return (e) => {
this.setState({ [propName]: e.target.value })
}
}
You can actually extract the setValue function and reuse it with any other component:
// in render
<input type="text"
value={this.state.username}
onChange={setValue(this, 'username')}
/>
// somewhere outside of the component
function setValue(component, propName) {
return (e) => {
component.setState({ [propName]: e.target.value })
}
}
I believe I've seen some quite popular React forms handling library which was doing exactly this, but in a bit smarter way — they have cached the generated function to avoid creating a bunch of new function objects on each render. Just can't recall how was it named — there are too much new libs in the react world :)