Input box w/ data
-
Keep track of which cell to edit via this.state.edit.
-
Render an input field when displaying the table if the row and column indices match the cell the user double-clicked.
-
Update the data array with the new value from the input field.
states
- edit: keep track of the location of the edit, null when no edit.
- data: a place to store data (new and old)
methods
- showEditor(): responsible for updating the edit state
- save(): gets the data from the input field and update to the data state. It also sets edit state back to null
event
- onDoubleClick: this means a new edit is coming, call showEditor()
-
onSubmit: this means the edit is done, call save()
代码
- jsx
<tbody onDoubleClick={this.showEditor}>
{this.state.data.map((row, rowidx) => (
<tr key={rowidx} data-row={rowidx}>
{row.map((cell, columnidx) => {
// <td key={idx}>{cell}</td>
const edit = this.state.edit;
if (edit && edit.row === rowidx && edit.column === columnidx) {
cell = (
<form onSubmit={this.save}>
<input type="text" defaultValue={cell} />
</form>
);
}
return <td key={columnidx}>{cell}</td>;
})}
</tr>
))}
</tbody>
- constructor
constructor(props){
super();
this.state = {
data: props.initialData,
sortby: null,
descending: false,
edit: null
};
this.sort = this.sort.bind(this);
this.showEditor = this.showEditor.bind(this);
this.save = this.save.bind(this);
}
- showEditor() & save()
showEditor(e) {
this.setState({
edit: {
row: parseInt(e.target.parentNode.dataset.row, 10),
column: e.target.cellIndex,
},
});
}
save(e) {
e.preventDefault(); // so page doesn't reload
// ... do the save
const input = e.target.firstChild; // e.target is the form, first child is the input field
const data = clone(this.state.data); // get copy of the data state
data[this.state.edit.row][this.state.edit.column] = input.value; // update data state
this.setState({
edit: null,
data,
}); // save the state
}