I created a reactJs page that allows an admin add a user to a platform. Now, instead of submitting the form for each new user, the admin can add as many users as possible before submitting the form. By default, one table row containing input fields is displayed and then on click of the add button, a new row is added and the admin can fill the necessary details.
I want to add an onChange event to the input fields for each new row. I don't know how to do as this is quite dynamic. The state will have to change as new rows is added. I don't know how to go about updating this state and adding the onChange event for each field in each row. Here is my existing code:
export default class Admins extends React.Component{
constructor(props){
super(props);
this.state = {
errors : '',
success : '',
rows : [1]
}
this.addRow = this.addRow.bind(this);
this.fetchRows = this.fetchRows.bind(this);
this.removeRow = this.removeRow.bind(this);
}
addRow(){
var last = this.state.rows[this.state.rows.length-1];
var current = last + 1;
this.setState({
rows : this.state.rows.concat(current)
});
}
removeRow(index){
var array = this.state.rows;
array.splice(index, 1)
this.setState({
rows : array
})
}
fetchRows(){
return this.state.rows.map((row, index) => (
//console.log(row, index)
<tr key={row}>
<td className="text-center">
<button type="button" onClick={(e)=> this.removeRow(index)} data-toggle="tooltip" className="btn btn-xs btn-danger"
data-original-title=""><i className="fa fa-trash"></i>
</button>
</td>
<td>
<input type="text" className="form-control" onChange={}/>
</td>
<td>
<input type="text" className="form-control" onChange={}/>
</td>
<td>
<input type="text" className="form-control" onChange={}/>
</td>
</tr>
));
}
render(){
return(
<div>
<Top/>
<SideBar/>
<div className="breadcrumb-holder">
<div className="container-fluid">
<ul className="breadcrumb">
<li className="breadcrumb-item"><Link to="/">Dashboard</Link></li>
<li className="breadcrumb-item active">Admins</li>
</ul>
</div>
</div>
<section className="forms">
<div className="container-fluid">
<header>
<h3 className="h5 display">Admins</h3>
</header>
<div className="row">
<div className="col-lg-6">
<h5 className="text-danger">{this.state.errors}</h5>
<h5 className="text-success">{this.state.success}</h5>
</div>
</div>
<div className="row">
<div className="col-lg-6">
<div className="card">
<div className="card-header d-flex align-items-center">
<h5></h5>
</div>
<div className="card-body">
<table className="table table-bordered">
<thead>
<tr>
<th width="5%">Actions</th>
<th>Name</th>
<th>Email</th>
<th>Password</th>
</tr>
</thead>
<tbody>
{this.fetchRows()}
<tr>
<td className="text-center">
<button type="button" onClick={this.addRow} data-toggle="tooltip" className="btn btn-xs btn-primary"
data-original-title=""><i className="fa fa-plus"></i>
</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
);
}
}
removeRow()you're setting thearrayvariable equal tothis.state.rows, but that doesn't create a new array, it creates a reference to that array. So on the next line when you callsplice()(which mutates the array that calls it), this will actually mutate the state itself. Useslice()to make a copy of the state array, e.g.let currentRows = this.state.rows.slice(0). Also, don't call variables things like 'array', give them meaningful names..rowis just an incrementing number). If there's nothing unique about them available from the data, you can generate a unique id and assign it to the row object when you add a row.