javascript - 如何将 onchange 事件绑定到特定行的元素?
问题描述
我正在获取所有用户的数据,并在表格中显示该数据。我能够获取特定行的用户 ID,现在我正在尝试为该特定行的元素添加 onchange 事件。当我单击编辑按钮时,所有输入字段都在取值,但所有值都在该类别下发生变化。例如,如果我单击编辑并开始输入名称,则名称列中的所有字段都在更改。我只想更改相应行上的特定字段
import React, { Component } from "react";
import { getAllDash, updateAdminUser } from "../fetchingData/api_calls";
import "./profile.css";
import { Table } from "reactstrap";
class AdminDash extends Component {
constructor(props) {
super(props);
this.state = {
users: [],
edit: false,
firstname: "",
lastname: "",
phone: "",
email: "",
error: false,
verification: false,
role: "user",
input: "",
};
}
componentDidMount() {
const token = localStorage.getItem("jwt");
getAllDash(token).then((data) => {
data.map((user_id, idx) => {
this.setState({
users: data,
});
});
});
}
editbtn = (id) => {
console.log("id is..", id);
this.setState((state) => ({
// edit: !this.state.edit,
users: state.users.map((csid) => {
if (csid.user_id === id.user_id) {
console.log(id.user_id);
return {
...csid,
edit: !state.edit,
log: console.log("state is if", !state.edit),
// edit: this.state.edit,
};
} else {
console.log("state is else", this.state.edit);
return csid;
}
}),
edit: !this.state.edit,
// log: console.log("state is edit", !this.state.edit),
// edit:state.edit
}));
this.editbtn = this.editbtn.bind(this);
};
renderTableData() {
return this.state.users.map((data, index) => {
const {
user_id,
user_firstname,
user_lastname,
user_phone,
user_email,
user_role,
user_verification,
} = data; //destructuring
return (
<tr key={user_id}>
<td> {++index}</td>
<td> {user_id}</td>
<td>
{" "}
<input
value={this.state.firstname}
onChange={(e) => {
this.setState({ firstname: e.target.value })}}
placeholder={user_firstname}
disabled={!this.state.edit}
/>
</td>
<td>
{" "}
<input
value={this.state.lastname}
onChange={(e) => this.setState({ lastname: e.target.value })}
placeholder={user_lastname}
disabled={!this.state.edit}
/>
</td>
<td>
{" "}
<input
value={this.state.email}
onChange={(e) => this.setState({ email: e.target.value })}
placeholder={user_email}
disabled={!this.state.edit}
/>
</td>
<td>
{" "}
<input
value={this.state.role}
// onChange={(e) => this.setState({ firstname: e.target.value })}
placeholder={user_role}
disabled={!this.state.edit}
/>
</td>
<td>
{" "}
<input
value={this.state.phone}
onChange={(e) => this.setState({ phone: e.target.value })}
placeholder={user_phone}
disabled={!this.state.edit}
/>
</td>
<td>
{" "}
<input
value={this.state.verification}
placeholder={user_verification}
disabled={!this.state.edit}
/>
</td>
<td>
<button onClick={(e) => this.editbtn(data, e)} key={data.user_id}>
{this.state.edit ? "Cancel" : "edit"}
</button>
<button>Save changes</button>
</td>
</tr>
);
});
}
render() {
return (
<div className="adminDash">
<Table>
<thead>
<tr>
<th id="number">No.</th>
<th>User Id</th>
<th>User First Name</th>
<th>User Last Name</th>
<th>User Email</th>
<th>User Role</th>
<th>User Phone</th>
<th>user verification</th>
<th>User status</th>
</tr>
</thead>
<tbody>{this.renderTableData()}</tbody>
</Table>
</div>
);
}
}
export default AdminDash;
解决方案
问题
除了edit
每行中的每个输入都使用单一状态之外,当您处于编辑模式时,每个输入都使用相同的状态来提供它们的value
属性。
主要问题是映射的行数据并没有真正被使用。
解决方案
更新
editbtn
回调以简单地切换编辑模式。不过,不要切换布尔值,而是在null
和用户之间切换,user_id
这样您就可以匹配要编辑的行。editbtn = (data) => { const { user_id } = data; this.setState((prevState) => ({ edit: prevState.edit === user_id ? null : user_id })); };
实施
componentDidUpdate
以根据当前edit
状态值填充或重置字段状态值。如果edit
为真,则在数组中搜索用户,users
如果找到,则填充状态,否则重置字段状态值。componentDidUpdate(prevProps, prevState) { if (prevState.edit !== this.state.edit) { if (this.state.edit) { const user = this.state.users.find( (user) => user.user_id === this.state.edit ); if (user) { this.setState({ firstname: user.user_firstname, lastname: user.user_lastname, phone: user.user_phone, email: user.user_email, verification: user.user_verification, role: user.user_role }); } } else { this.setState((prevState) => ({ firstname: "", lastname: "", phone: "", email: "", verification: false, role: "user" })); } } }
计算一个
isEditable
值以传递给disabled
输入的属性。此外,如果特定用户/行是可编辑的,则有条件地传递用户数据值或存储编辑值的字段状态
renderTableData() { return this.state.users.map((data, index) => { const { user_id, user_firstname, ... } = data; //destructuring const isEditable = this.state.edit === user_id; return ( <tr key={user_id}> <td> {index + 1}</td> <td> {user_id}</td> <td> <input value={isEditable ? this.state.firstname : user_firstname} onChange={(e) => { this.setState({ firstname: e.target.value }); }} placeholder={user_firstname} disabled={!isEditable} /> </td> ...
为了完成,实现“保存数据”按钮的回调。这将获取字段状态数据并更新
users
状态数组中的用户记录。这也清除了字段输入状态值并重置edit
返回以null
使该行退出编辑模式。saveData = () => { this.setState((prevState) => ({ users: prevState.users.map((user) => user.user_id === prevState.edit ? { ...user, user_firstname: prevState.firstname, user_lastname: prevState.lastname, user_phone: prevState.phone, user_email: prevState.email, user_role: prevState.role, user_verification: prevState.verification } : user ), edit: null, firstname: "", lastname: "", phone: "", email: "", verification: false, role: "user" })); };
中的小问题
componentDidMount
。你遍历你的data
数组并将一堆状态更新排入队列,这些状态更新只是将相同的更新排入队列。这里不需要一个data.map
,一个this.setState({ users: data });
就足够了。componentDidMount() { const token = localStorage.getItem("jwt"); getAllDash(token).then((data) => { this.setState({ users: data }); }); }
演示
完整的沙盒代码:
class AdminDash extends Component {
constructor(props) {
super(props);
this.state = {
users: [],
edit: null,
firstname: "",
lastname: "",
phone: "",
email: "",
error: false,
verification: false,
role: "user",
input: ""
};
}
componentDidMount() {
this.setState({ users: data });
}
componentDidUpdate(prevProps, prevState) {
if (prevState.edit !== this.state.edit) {
if (this.state.edit) {
const user = this.state.users.find(
(user) => user.user_id === this.state.edit
);
if (user) {
this.setState({
firstname: user.user_firstname,
lastname: user.user_lastname,
phone: user.user_phone,
email: user.user_email,
verification: user.user_verification,
role: user.user_role
});
}
} else {
this.setState((prevState) => ({
firstname: "",
lastname: "",
phone: "",
email: "",
verification: false,
role: "user"
}));
}
}
}
editbtn = (data) => {
console.log("data is..", data);
const { user_id } = data;
this.setState((prevState) => ({
edit: prevState.edit === user_id ? null : user_id
}));
};
saveData = () => {
this.setState((prevState) => ({
users: prevState.users.map((user) =>
user.user_id === prevState.edit
? {
...user,
user_firstname: prevState.firstname,
user_lastname: prevState.lastname,
user_phone: prevState.phone,
user_email: prevState.email,
user_role: prevState.role,
user_verification: prevState.verification
}
: user
),
edit: null,
firstname: "",
lastname: "",
phone: "",
email: "",
verification: false,
role: "user"
}));
};
renderTableData() {
return this.state.users.map((data, index) => {
const {
user_id,
user_firstname,
user_lastname,
user_phone,
user_email,
user_role,
user_verification
} = data; //destructuring
const isEditable = this.state.edit === user_id;
return (
<tr key={user_id}>
<td> {index + 1}</td>
<td> {user_id}</td>
<td>
<input
value={isEditable ? this.state.firstname : user_firstname}
onChange={(e) => {
this.setState({ firstname: e.target.value });
}}
placeholder={user_firstname}
disabled={!isEditable}
/>
</td>
<td>
<input
value={isEditable ? this.state.lastname : user_lastname}
onChange={(e) => this.setState({ lastname: e.target.value })}
placeholder={user_lastname}
disabled={!isEditable}
/>
</td>
<td>
<input
value={isEditable ? this.state.email : user_email}
onChange={(e) => this.setState({ email: e.target.value })}
placeholder={user_email}
disabled={!isEditable}
/>
</td>
<td>
<input
value={isEditable ? this.state.role : user_role}
// onChange={(e) => this.setState({ firstname: e.target.value })}
placeholder={user_role}
disabled={!isEditable}
/>
</td>
<td>
<input
value={isEditable ? this.state.phone : user_phone}
onChange={(e) => this.setState({ phone: e.target.value })}
placeholder={user_phone}
disabled={!isEditable}
/>
</td>
<td>
<input
value={isEditable ? this.state.verification : user_verification}
placeholder={user_verification}
disabled={!isEditable}
/>
</td>
<td>
<button onClick={() => this.editbtn(data)}>
{isEditable ? "Cancel" : "edit"}
</button>
<button onClick={this.saveData}>Save changes</button>
</td>
</tr>
);
});
}
render() {
return (
<div className="adminDash">
<Table>
<thead>
<tr>
<th id="number">No.</th>
<th>User Id</th>
<th>User First Name</th>
<th>User Last Name</th>
<th>User Email</th>
<th>User Role</th>
<th>User Phone</th>
<th>user verification</th>
<th>User status</th>
</tr>
</thead>
<tbody>{this.renderTableData()}</tbody>
</Table>
</div>
);
}
}
推荐阅读
- python - 如何连接数组中列中的值
- python - 如何生成一个值位于两个现有列之间的新列
- bash - 为什么我的 Bash 脚本显示“找不到命令”?
- java - 如何使用 PowerMockito 从单例类中模拟带有参数的单个静态方法
- kotlin - 在 Kotlin 中模拟属性的包隐私
- plc - 如何在没有 PLC 的情况下运行 Twincat 程序?
- flutter - 如何将使用相机包录制的视频保存到 Flutter 中的图库?
- python - 无法在 Powershell 中的同一网络上的远程计算机上激活 conda 虚拟环境
- python - 在 Python 中使用条件值进行投资组合优化
- php - 有没有办法在不使用“_server”超级全局变量的情况下做到这一点?`PhraseBuilder::comparePhrases`