community,
I'm trying to build a table where its rows are rendered based on an array of objects:
this.state = {
tableContent: [
{
id: this.state.tableContent.length,
firstname:"",
lastname:""
},
...
]
Each row displays one object. (2 columns in this case, n rows) Each cell is also an input field, so users can manipulate the table:
<tbody>
{this.state.tableContent.map((row) => {
return(
<tr key={row.id}>
<td><input value={row.firstname} onChange={this.handleFirstNameChange}> </input></td>
...
</tr>
)
})}
</tbody>
I want each cell / input field to display the change when the user changes the input value and as such the state. Because I'm prepopulating the input field with value={row.firstname}
I need to define an onChange
handler function that changes the state/value of the target object's firstname
property.
So how does my onChange
handler function look like? I tried using spreads, but to no avail so far...
Some thoughts: Using the standard procedure doesn't work because I have a nested state (Array of objects):
handleChange = (event) => { this.setState({ firstname: event.target.value }) }
Trying to use the spread operator results in some weird mess as well: (this code here is somewhat wrong: maybe you can fix it?)
handleFirstNameChange = (event) => {
const {tableContent} = {...this.state};
const currentState = tableContent;
const { firstname, value } = event.target;
currentState[0] = value;
this.setState({ tableContent: currentState});
}
I appreciate any help!
edit: The code below seems to nearly work. (thanks @Nikhil ) However now, whenever the user types into the input field, every letter they type will replace the existing letter / value of 'row.firstname'. Also, state doesn't refresh automatically so only the last-typed letter would show up / persist. What I need the input field to have is a functionality just like any casual input field. event.persist(); seems to be needed to keep the event value.
handleFirstNameChange = (id, event) => {
event.persist();
this.setState(prevState => {
tableContent : prevState.tableContent.forEach((row) => {
if(row.id === id) { row.firstname = event.target.value}
})
})
}
input looks like this:
onChange={(event) => this.handleWNRChange(row.id,event)}
I think something like this would work.
const handleFirstNameChange = (id, event) => {
event.preventDefault();
const {tableContext} = this.state;
const myRowIndex = tableContext.findIndex((row) => row.id === id);
tableContext[myRowIndex].firstname = event.target.value;
this.setState({ tableContext });
}
This should be all you need. Just assign this method to the onChange
of the input
element. Like so:
onChange={(event) => this.handleFirstNameChange(row.id, event)}
May be this will help
{this.state.tableContent.map((row, index) => {
return(
<tr key={row.firstname}>
<td><input value={row.firstname}
onChange={(event)=>this.handleFirstNameChange(event, index)> </input></td>
</tr>
)
})
}
handleFirstNameChange(event, index){
this.setState((prevState => {
tableContent : prevState.tableContent.forEach((row,i)=>{
if(index === i) row.firstname = event.target.value
})
})
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.