Reputation: 31252
I want a container with table that has one column "enabled" which can be toggled. I want to save the state of toggle in object I used to display the row (In the example below, I want to store it in enable
attribute of student object). I have table and toggle button displaying properly. But the toggle button is not clickable/togglable and doesnt store the state. live code here.
Here is my code
class student {
constructor(id, name, age,email,enable) {
this.id = id;
this.name = name;
this.age = age;
this.email = email;
this.enable = enable;
}
}
const Switch = ({ isOn, handleToggle}) => {
return (
<>
<input
checked={isOn}
onChange={handleToggle}
className="react-switch-checkbox"
id={`react-switch-new`}
type="checkbox"
/>
<label
className="react-switch-label"
htmlFor={`react-switch-new`}
>
<span className={`react-switch-button`} />
</label>
</>
);
};
class Table extends React.Component {
constructor(props) {
super(props)
this.state = {
students: [ new student(1, 'foo', 12, '[email protected]', true),
new student(2, 'bar', 22, '[email protected]', false),
new student(3, 'foobar', 44, '[email protected]', true),
new student(4, 'foofoo',57, '[email protected]', false)
]
}
}
renderTableHeader() {
let header = Object.keys(this.state.students[0])
return header.map((key, index) => {
return <th key={index}>{key.toUpperCase()}</th>
})
}
renderTableData() {
return this.state.students.map((student, index) => {
const { id, name, age, email, enable } = student //destructuring
//const [value, setValue] = useState(false);
return (
<tr key={id}>
<td>{id}</td>
<td>{name}</td>
<td>{age}</td>
<td>{email}</td>
<td><Switch
isOn={enable}
handleToggle={() => student.enable=!enable}
/></td>
</tr>
)
})
}
render() {
return (
<div>
<h1 id='title'>React Dynamic Table</h1>
<table id='students'>
<tbody>
<tr>{this.renderTableHeader()}</tr>
{this.renderTableData()}
</tbody>
</table>
</div>
)
}
}
ReactDOM.render(<Table />, document.getElementById('root'));
Here is the screenshot of how page looks
Upvotes: 1
Views: 5271
Reputation: 20755
The issue is, you cannot directly change the state like,
handleToggle={() => student.enable=!enable}
This will never change your state. To change your state you must use setState
.
You should have a dedicated function to toggle your state,
handleToggle = (id) => {
this.setState({
students: this.state.students.map(std => {
if(parseInt(std.id) === parseInt(id)){ //parse id to integer for safer side
return {...std, enable: !std.enable}
}else{
return std;
}
})
})
}
You should provide this function to your Switch
. Also provide id
for updation.
<Switch
isOn={enable}
id={id} //provide id for updation
handleToggle={this.handleToggle} //provide function reference
/>
You need to make some changes to your Switch
,
const Switch = ({ isOn, handleToggle, id}) => { //take prop id
return (
<>
<input
checked={isOn}
onChange={() => handleToggle(id)} //call handleToggle using id
className="react-switch-checkbox"
id={`react-switch-new${id}`} // Make it unique by adding id
type="checkbox"
/>
<label
className="react-switch-label"
htmlFor={`react-switch-new${id}`} // Make it unique by adding id
>
<span className={`react-switch-button`} />
</label>
</>
);
};
Upvotes: 3