我如何使用 React 创建一个有条件的 editable input/cells table?
How can I create a table with conditionally editable input/cells using React?
我有一个 table 这样的:
当用户点击 Edit
按钮时,<input>
应该出现在它的位置。
如果用户点击另一个 Edit
按钮,这个按钮也将被替换为 <input>
,并且之前的 <input>
应该消失并显示 Edit
再次按钮。
简而言之,一次只能有一个字段处于编辑模式。
这是我的首字母state
:
state = {
editnameEnable: false,
editemailEnable: false,
editaddressEnable: false,
edittelephone_noEnable: false,
}
这是我的edit()
方法:
edit = value => {
var address_element = ['name','address','email','telephone_no'];
address_element = address_element.filter(element => element !== value);
address_element.map( val => this.setState({[`edit${val}Enable`]: false}));
this.setState({[`edit${value}Enable`]: true}, ()=>{
console.log(this.state);
});
}
这是我的 render
方法中 JSX 的一部分:
<td>{
this.state[`edit${this.props.item}Enable`] ? ( <input type="text"/> ) : (
<span
className="edit"
onClick={ () => this.edit(this.props.item) }>Edit</span>
)
}</td>
问题是当我点击一个Edit
按钮时,<input>
出现,但是当我点击另一个Edit
按钮时,之前的<input>
没有出现消失。
使用初始设置为 null
的单个 editableField
属性 怎么样?
然后,当您单击 Edit
按钮时,将 editableField
设置为该字段的名称,并在 render
中检查每个字段是否 editableField
匹配或不匹配其名称以呈现 Edit
按钮或输入字段。
像这样:
class FieldCell extends React.Component {
constructor(props) {
super(props);
}
focusField = (element) => element && element.focus();
render() {
const editElement = this.props.isEditable ? (
<input type="text" ref={ this.focusField }/>
) : (
<button onClick={ () => this.props.onEdit() }>EDIT</button>
);
return (<td className="textLeft">{ editElement }</td>);
}
}
class UserData extends React.Component {
constructor(props) {
super(props);
this.state = {
editableField: null,
};
}
render() {
const editableField = this.state.editableField;
const rows = ['Name', 'Address', 'Telephone No.', 'E-Mail'].map((field) => {
const isEditable = field === editableField;
return (
<tr key={ field }>
<td>{ field }</td>
<FieldCell isEditable={ isEditable } onEdit={ () => this.setState({ editableField: field })}></FieldCell>
</tr>
);
});
return (<table>{ rows }</table>);
}
}
ReactDOM.render(<UserData />, document.getElementById('app'));
body {
font-family: monospace;
font-size: 13px;
}
table {
border: 2px solid #000;
border-collapse: collapse;
text-align: right;
width: 100%;
}
td {
border: 2px solid #000;
padding: 4px;
width: 50%;
overflow: hidden;
}
.textLeft {
text-align: left;
user-select: none;
}
button,
input {
border: 2px solid black;
padding: 4px 8px;
margin: 0;
font-family: monospace;
font-size: 13px;
box-sizing: border-box;
background: none;
outline: none;
}
button:hover,
button:focus,
input:hover,
input:focus {
border-color: blue;
color: blue;
}
button {
font-weight: bold;
}
input {
width: 50%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
我有一个 table 这样的:
当用户点击 Edit
按钮时,<input>
应该出现在它的位置。
如果用户点击另一个 Edit
按钮,这个按钮也将被替换为 <input>
,并且之前的 <input>
应该消失并显示 Edit
再次按钮。
简而言之,一次只能有一个字段处于编辑模式。
这是我的首字母state
:
state = {
editnameEnable: false,
editemailEnable: false,
editaddressEnable: false,
edittelephone_noEnable: false,
}
这是我的edit()
方法:
edit = value => {
var address_element = ['name','address','email','telephone_no'];
address_element = address_element.filter(element => element !== value);
address_element.map( val => this.setState({[`edit${val}Enable`]: false}));
this.setState({[`edit${value}Enable`]: true}, ()=>{
console.log(this.state);
});
}
这是我的 render
方法中 JSX 的一部分:
<td>{
this.state[`edit${this.props.item}Enable`] ? ( <input type="text"/> ) : (
<span
className="edit"
onClick={ () => this.edit(this.props.item) }>Edit</span>
)
}</td>
问题是当我点击一个Edit
按钮时,<input>
出现,但是当我点击另一个Edit
按钮时,之前的<input>
没有出现消失。
使用初始设置为 null
的单个 editableField
属性 怎么样?
然后,当您单击 Edit
按钮时,将 editableField
设置为该字段的名称,并在 render
中检查每个字段是否 editableField
匹配或不匹配其名称以呈现 Edit
按钮或输入字段。
像这样:
class FieldCell extends React.Component {
constructor(props) {
super(props);
}
focusField = (element) => element && element.focus();
render() {
const editElement = this.props.isEditable ? (
<input type="text" ref={ this.focusField }/>
) : (
<button onClick={ () => this.props.onEdit() }>EDIT</button>
);
return (<td className="textLeft">{ editElement }</td>);
}
}
class UserData extends React.Component {
constructor(props) {
super(props);
this.state = {
editableField: null,
};
}
render() {
const editableField = this.state.editableField;
const rows = ['Name', 'Address', 'Telephone No.', 'E-Mail'].map((field) => {
const isEditable = field === editableField;
return (
<tr key={ field }>
<td>{ field }</td>
<FieldCell isEditable={ isEditable } onEdit={ () => this.setState({ editableField: field })}></FieldCell>
</tr>
);
});
return (<table>{ rows }</table>);
}
}
ReactDOM.render(<UserData />, document.getElementById('app'));
body {
font-family: monospace;
font-size: 13px;
}
table {
border: 2px solid #000;
border-collapse: collapse;
text-align: right;
width: 100%;
}
td {
border: 2px solid #000;
padding: 4px;
width: 50%;
overflow: hidden;
}
.textLeft {
text-align: left;
user-select: none;
}
button,
input {
border: 2px solid black;
padding: 4px 8px;
margin: 0;
font-family: monospace;
font-size: 13px;
box-sizing: border-box;
background: none;
outline: none;
}
button:hover,
button:focus,
input:hover,
input:focus {
border-color: blue;
color: blue;
}
button {
font-weight: bold;
}
input {
width: 50%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>