Currently when I click on any button, all edit buttons change to update buttons, but I just want to trigger the row where the action was actually performed without triggering any other button. I am using the below code snippet in my ReactJs project. can anyone please help in suggesting something that would work for me. Please note that I am not using hooks at this point.
import React from 'react';
class GridSample extends React.Component {
constructor() {
super();
this.state = {
clicked: false,
};
this.handleOnedit = this.handleOnedit.bind(this);
this.handleCancel = this.handleCancel.bind(this);
this.handleUpdate = this.handleUpdate.bind(this);
}
handleOnedit = (event) => {
const par = event.target.parentNode;
const suppar = par.parentNode;
suppar.setAttribute('contenteditable', true);
suppar.focus();
this.setState({ clicked: true });
};
handleOndelete() {
alert('this is delete button');
}
handleCancel() {
window.location.replace(false);
}
handleUpdate() {
this.setState({
clicked: false,
});
}
render() {
console.clear();
return (
<div>
<table>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Age</th>
<th>Action</th>
</tr>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
<td>
{!this.state.clicked ? (
<input type="button" value="Edit" onClick={this.handleOnedit} />
) : (
<input
type="button"
value="Update"
onClick={this.handleUpdate}
/>
)}
{this.state.clicked ? (
<input
type="button"
value="Cancel"
onClick={this.handleCancel}
/>
) : (
<input
type="button"
value="Delete"
onClick={this.handleOndelete}
/>
)}
</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
<td>
{!this.state.clicked ? (
<input type="button" value="Edit" onClick={this.handleOnedit} />
) : (
<input
type="button"
value="Update"
onClick={this.handleUpdate}
/>
)}
{this.state.clicked ? (
<input
type="button"
value="Cancel"
onClick={this.handleCancel}
/>
) : (
<input
type="button"
value="Delete"
onClick={this.handleOndelete}
/>
)}
</td>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
<td>80</td>
<td>
{!this.state.clicked ? (
<input type="button" value="Edit" onClick={this.handleOnedit} />
) : (
<input
type="button"
value="Update"
onClick={this.handleUpdate}
/>
)}
{this.state.clicked ? (
<input
type="button"
value="Cancel"
onClick={this.handleCancel}
/>
) : (
<input
type="button"
value="Delete"
onClick={this.handleOndelete}
/>
)}
</td>
</tr>
</table>
</div>
);
}
}
export default GridSample;
CodePudding user response:
You should try passing the index as a parameter and do the test on it instead of changing the value to true or false of your state.clicked (I added a link to an sandbox that uses your calss
import React from "react";
class GridSample extends React.Component {
constructor() {
super();
this.state = {
clicked: NaN,
items: [
{ Firstname: "Jack", Lastname: "Ali", Age: 25 },
{ Firstname: "Adam", Lastname: "Alan", Age: 55 }
]
};
this.handleOnedit = this.handleOnedit.bind(this);
this.handleCancel = this.handleCancel.bind(this);
this.handleUpdate = this.handleUpdate.bind(this);
}
handleOnedit = (event, i) => {
const par = event.target.parentNode;
const suppar = par.parentNode;
suppar.setAttribute("contenteditable", true);
suppar.focus();
this.setState({ ...this.state, clicked: i });
};
handleOndelete() {
alert("this is delete button");
}
handleCancel() {
window.location.replace(false);
}
handleUpdate(event, i) {
this.setState({ ...this.state, clicked: i });
}
render() {
console.clear();
return (
<div>
<table>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Age</th>
<th>Action</th>
</tr>
{this.state.items.map((e, i) => {
return (
<tr key={i}>
<td>{e.Firstname}</td>
<td>{e.Lastname}</td>
<td>{e.Age}</td>
<td>
{!this.state.clicked === i ? (
<input
type="button"
value="Edit"
onClick={(event) => this.handleOnedit(event, i)}
/>
) : (
<input
type="button"
value="Update"
onClick={(event) => this.handleUpdate(event, i)}
/>
)}
{this.state.clicked === i ? (
<input
type="button"
value="Cancel"
onClick={(event) => this.handleCancel(event, i)}
/>
) : (
<input
type="button"
value="Delete"
onClick={(event) => this.handleOndelete(event, i)}
/>
)}
</td>
</tr>
);
})}
</table>
</div>
);
}
}
export default GridSample;
Here is the example : https://codesandbox.io/s/react-class-forked-ze3o9?file=/index.js
CodePudding user response:
Basically, you need to store your data in an array, it will help render something like a table:
const data = [
{ id: 1, firstName: 'Jill', lastName: 'Smith', age: 50 },
{ id: 2, firstName: 'Eve', lastName: 'Jackson', age: 94 },
{ id: 3, firstName: 'John', lastName: 'Doe', age: 80 },
];
So now you'll be able to render every row using map
:
{data.map(({ id, firstName, lastName, age }) => (
<tr key={id}>
<td>{firstName}</td>
<td>{lastName}</td>
<td>{age}</td>
<td>
{this.state.updateId === id ? (
<input
type="button"
value="Edit"
onClick={this.handleOnedit}
/>
) : (
<input
type="button"
value="Update"
onClick={() => this.handleUpdate(id)}
/>
)}
{this.state.clicked ? (
<input
type="button"
value="Cancel"
onClick={this.handleCancel}
/>
) : (
<input
type="button"
value="Delete"
onClick={this.handleOndelete}
/>
)}
</td>
</tr>
))}
To distinguish each row, you should have a state value like updateId
to know which one you're editing:
this.state = {
updateId: -1,
};
Checkout working example: https://stackblitz.com/edit/react-8aky3r