I have got Django Rest Framework backend and I am trying to post data there via React. Fetching the data is working fine. If I tried to post data with only one input it also worked fine. But when I try add more inputs, it does not work and I dont know how to handle multiple inputs..
React Code:
class Activity2project extends React.Component {
constructor(props) {
super(props);
this.state = {
virtualProjectList:[],
activeItem:{
id:null,
project_name:'',
project_name_RnD:'',
},
this.handleSubmit = this.handleSubmit.bind(this)
this.handleChange = this.handleChange.bind(this)
this.fetchVirtualProjects = this.fetchVirtualProjects.bind(this)
}
handleChange(e){
var name = e.target.name
var value = e.target.value
this.setState({
activeItem:{
...this.state.activeItem,
project_name:e.target.value,
project_name_RnD:e.target.value,
}
})
}
render(){
<div>
<input onChange={this.handleChange} type='text' id='virtual_project' name='virtual_project_name' value={this.state.activeItem.project_name} placeholder='Project Name' ></input>
<input onChange={this.handleChange} type='text' id='virtual_project_RnD' name='virtual_project_name_RnD' value={this.state.activeItem.project_name_RnD} placeholder='Project Name RnD' ></input>
<input id='submit' type='submit' name='Add'></input>
</div>
}
With this it writes the same value into inputs and I dont now how to distinguish these two inputs.
you can give your input fields ids that matches the attributes of your state:
<input onChange={this.handleChange} type='text' id='project_name' name='virtual_project_name' value={this.state.activeItem.project_name} placeholder='Project Name' ></input>
<input onChange={this.handleChange} type='text' id='project_name_RnD' name='virtual_project_name_RnD' value={this.state.activeItem.project_name_RnD} placeholder='Project Name RnD' ></input>
and then in changeHandler:
let id = event.target.id;
// then using computed property name
activeItem: {
...this.state.activeItem,
[id]: event.target.value
}
});
You can use [] brackets to bind the value of the object key to the name of the input.
For example:
handleChange(e) {
var name = e.target.name;
var value = e.target.value;
this.setState({
activeItem: {
...this.state.activeItem,
[name]: e.target.value
},
});
}
Your current code is attempting to alter both inputs at the same time. That's the reason why you can see both inputs adding the same text, as your app can't differentiate between the targets.
The following code will allow your app to see the target, check its name, and then handleChange will set the state assuming the name matches one of the available options.
As a result, the name of the inputs should reflect the state name, like so:
<input onChange={this.handleChange} type='text' id='virtual_project' name='project_name' value={this.state.activeItem.project_name} placeholder='Project Name' ></input>
<input onChange={this.handleChange} type='text' id='virtual_project_RnD' name='project_name_RnD' value={this.state.activeItem.project_name_RnD} placeholder='Project Name RnD' ></input>
And then changing handleChange to the following should work:
handleChange = (e) => {
this.setState({ [e.target.name]: e.target.value })
}
Hope that works.
Related
I'm not very proficient with React. I'm working with a dynamic form where users should be able to dynamically add and remove input fields. I'm unable to save inputs into variables dynamically however.
Code:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
values: [],
type:[],
name: '',
frequency: '',
};
}
handleMetric(i, event) {
let values = [...this.state.values];
values[i] = event.target.value;
this.setState({ values });
console.log("Metrics: ")
console.log(values)
}
handleThreshold(i, event) {
let values = [...this.state.values];
values[i] = event.target.value;
this.setState({ values });
console.log("Threshold: ")
console.log(values)
}
addClick(){
this.setState(prevState => ({ values: [...prevState.values, '']}))
}
removeClick(i){
let values = [...this.state.values];
values.splice(i,1);
this.setState({ values });
}
createUI(){
return this.state.values.map((el, i) =>
<div key={i}>
<input type="text" value={el||''} onChange={this.handleChange.bind(this, i)} />
<input type='button' value='remove' onClick={this.removeClick.bind(this, i)}/>
</div>
)
}
render() {
return (
<div>
<div className="card">
<form onSubmit={this.handleSubmit}>
<Form.Item name="Type of metrics" label="Metric" htmlFor="type">
<Select
value={Select}
onChange={this.handleMetric}
options={metrics}
/>
</Form.Item>
<Form.Item name="amount" label="Threshold Score" htmlFor="threshold">
<Slider marks={marks} name="threshold" onChange={this.handleThreshold} />
</Form.Item>
</Form>
{this.createUI()}
<input type='button' value='add more' onClick={this.addClick.bind(this)}/>
<input type="submit" value="Submit" />
</form>
</div>
</div>
);
}
}
export default App
Both handleThreshold and handleMetric functions are not working, and giving the following errors:
Would really appreciate some help in getting the variables stored in the arrays dynamically.
Turn the class methods into class property initializers with arrow functions so this is always the component instance:
handleMetric = (i, event) => {
let values = [...this.state.values];
values[i] = event.target.value;
this.setState({ values });
console.log("Metrics: ")
console.log(values)
};
handleThreshold = (i, event) => {
let values = [...this.state.values];
values[i] = event.target.value;
this.setState({ values });
console.log("Threshold: ")
console.log(values)
};
You solved this for another callback by doing this.addClick.bind(this) inside the render method. Both approaches work. Doing the arrow function declaration means only 1 function is created in the life of the component whereas .bind in render means 1 function is created per call to render. This will likely have no recognizable performance change for your app but is something to consider.
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 somewhat new to react, and I am having trouble recognizing whats causing my form to be broken. The submit button works fine and the name adds fine, but i cannot type into my price text-field for some reason. when adding items to the list, the dollar sign for price is adding, but i cant type anything into the price field.
import React, { Component } from 'react';
class ItemForm extends Component {
state = { name: '', price: ''}
handleChange = (e) => {
const { name, value } = e.target
this.setState({ [name]: value })
}
handleSubmit = (e) => {
//stop page from reloading
e.preventDefault();
//add item to groceries array
const { addItem } = this.props
addItem(this.state.name, this.state.price)
// this.props.addItem(this.state.price)
//clear form on submit
this.setState({name: '', price: ''})
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<input
required
placeholder='add Grocery Item'
name="name"
value={this.state.name}
onChange={this.handleChange}
/>
<br />
<input
placeholder='add price (optional)'
name="price"
value={this.state.price}
onChange={this.handleChange}
/>
<br />
<input class = "btn btn-primary" type = "submit" value =
"Add" />
</form>
)
}
}
export default ItemForm;
I think you accidentally put price="price" instead of name="price"
Am trying to build form inputs in reactjs. the code below works for just one form inputs.
Now I want to add two more form inputs as per
Firstname <input type="text" id="fname" name="fname"><br>
Lastname <input type="text" id="lname" name="lname"><br>
below is the working code that I want to implement the two form inputs above.
source
https://reactjs.org/docs/forms.html
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
The best way I've found to manage forms in React is to make sure each of your <input> tags has a name value. Then ensure that your component's state has fields for each input that matches the name exactly.
In your onChange handler, you can then say:
handleChange(event) {
this.setState({ [event.target.name]: event.target.value });
}
This will update the state with change to any of the inputs, and apply the change to that specific state value.
Then for handleSubmit, you send those values from state to where ever you need to process the form information.
try this one
handleChange(event){
this.setState({[event.target.name]:event.target.value});
this.setState({[event.target.name]:event.target.value});
}
I tried to build a app use ReactJS by ES6
class MyApp extends React.Component{
constructor(props){
super(props);
this.state = {
employee:{
name: 'hello',
birthday: ''
},
price: ''
}
this.handleValueChange = this.handleValueChange.bind(this);
}
handleValueChange(event){
valueName = event.target.name
this.setState({[valueName]: event.target.value});
};
render(){
return(
<form>
<input type="text" placeholder="name" value={this.state.employee.name} onChange={this.handleValueChange} name="name"/>
<input type="text" placeholder="name" value={this.state.price} onChange={this.handleValueChange} name="price"/>
</form>
)
}
}
As my Code, I used handleVauleChange in onChange event to change the default state of the input html tag.If the data in this.state is object(like employee), the handleVauleChange function will not work, but the data is like price, it will work fine.
Why has it happened?
Your setState for the name input should be like this...
this.setState({
employee: {
[valueName]: event.target.value
}
});
Not sure how dynamic the state structure you need but for one level deep structure, you can do something like this...
handleValueChange(event) {
const valueName = event.target.name;
const parent = valueName.indexOf('.') !== -1 ? valueName.split('.')[0] : false;
if (parent) {
this.setState({
[parent]: {
[valueName]: event.target.value
}
});
} else {
this.setState({
[valueName]: event.target.value
});
}
}
and on your input fields...
<input
type="text"
placeholder="name"
name="employee.name"
value={this.state.employee.name}
onChange={this.handleValueChange} />
<input
type="text"
placeholder="price"
name="price"
value={this.state.price}
onChange={this.handleValueChange} />
created jsbin:
http://jsbin.com/vopixexixe/edit?js,console,output#J:L14
In name input your setting input value from this.state.employee.name which is "hello" but on change your setting changed value to this.state.name
but in case of price your setting input value from this.state.price and updating to this.state.price, so value is reflecting.
In case of "name" you edit state.name and you want to edit state.employee.name I think