无法在 DataTable React Js 中设置输入元素的初始值和 onchange
Not able to set initial values and onchange of input elelements in DataTable React Js
我有一个从父组件到子组件 (DataTable) 的数据集。我正在用传入的数据创建一个数据表。我能够创建数据表,但我面临 2 个问题:
- 我无法在 Datatable 的输入元素中写入内容
- 我无法根据传入的数据设置输入框的初始值
我的目标是我想为所有输入设置一些初始值(动态的,基于数据)并且用户应该能够编辑输入值。
我是 React 的新手,我无法理解这个问题
以下是我的代码:
import react, {Component} from 'react';
import $ from 'jquery';
export default class Datatable extends Component{
constructor(props){
super(props)
this.state = {
value:""
}
this.generateHeader = this.generateHeader.bind(this);
this.generateTableData = this.generateTableData.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleChange(event){
console.log("change clicked");
this.setState({value: event.target.value});
}
generateHeader(){
const columnHeader = ["Deposit name", "Amount"]
let res=[];
for(var i =0; i < columnHeader.length; i++){
res.push(<th key={columnHeader[i]}>{columnHeader[i]}</th>)
}
return res;
}
generateTableData(){
let tableData = this.props.snapshotData.data.deposits;
let invenstments = tableData.Investment;
let liquid = tableData.Liquid;
let savings = tableData.Savings;
let arr = $.merge(this.createRow(invenstments), this.createRow(liquid))
let res = $.merge(arr, this.createRow(savings));
return res;
}
createRow(data){
let res=[];
for(var i=0; i < data.length; i++){
res.push(
<tr>
<td key={data[i].name}>{data[i].deposit_name}</td>
<td key={data[i].id}><input type="text" value={this.state.value} onChange={this.handlehange} /></td>
</tr>
)
}
return res;
}
render(){
return(
<div className="row">
<div className="col-12">
<div className="card">
<div className="card-header">
<h3 className="card-title">DataTable with default features</h3>
</div>
<div className="card-body">
<table id="example1" className="table table-bordered table-striped">
<thead>
<tr>
{this.generateHeader()}
</tr>
</thead>
<tbody>
{this.generateTableData()}
</tbody>
<tfoot>
<tr>
{this.generateHeader()}
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
)
}
}
我想设置为input values的初始值是:data[i].amount in createRow(data) method.
输入json格式如下:
{
"data": {
"deposits": {
"Investment": [
{
"amount": 1000.0,
"deposit_name": "Test 12",
"id": 12
},
{
"amount": 1000.0,
"deposit_name": "Test 13",
"id": 13
}
],
"Liquid": [
{
"amount": 1000.0,
"deposit_name": "Test 3",
"id": 3
}
],
"Savings": [
{
"amount": 1000.0,
"deposit_name": "Test 1",
"id": 1
},
{
"amount": 1000.0,
"deposit_name": "Test 2",
"id": 2
}
]
}
},
"message": "success",
"status": true
}
根据您在代码中分享的详细信息,我假设 Datatable
组件的使用方式如下:
<Datatable
snapshotData={{
data: {
deposits: {
Investment: [{ amount: 0, deposit_name: "", id: "" }, ...],
Liquid: [{ amount: 0, deposit_name: "", id: "" }, ...],
Savings: [{ amount: 0, deposit_name: "", id: "" }, ...],
},
},
}}
/>
从那里开始,在不过多更改代码的情况下,我们需要确保初始状态包含正确的数据
我们会将您的逻辑从 generateTableData
移至构建阶段
这将帮助我们启动具有正确数据结构的组件:
constructor(props) {
super(props);
let tableData = this.props.snapshotData.data.deposits;
let invenstments = tableData.Investment;
let liquid = tableData.Liquid;
let savings = tableData.Savings;
let merged = [].concat(invenstments).concat(liquid).concat(savings);
let state = {
items: {},
ids: []
};
for (var i = 0; i < merged.length; i++) {
state.items[merged[i].id] = merged[i];
state.ids.push(merged[i].id);
}
this.state = state;
this.generateHeader = this.generateHeader.bind(this);
this.generateTableData = this.generateTableData.bind(this);
this.handleChange = this.handleChange.bind(this);
}
根据上面的逻辑,我们将有一个 this.state
看起来像:
this.state = {
items: {
12: {
"amount": ...,
"deposit_name": ...,
"id": ...,
},
13: {...}
},
ids: [12, 13, 3]
}
此结构帮助我们“查找和更新”this.state.items
中的值,并使用 this.state.ids
迭代这些对象
现在 handleChange
,我们需要查找正确的对象并为反应生成新状态:
handleChange(event) {
let nextState = Object.assign({}, this.state);
nextState.items[event.target.id].amount = event.target.value;
this.setState(nextState);
}
我们在这里使用 Object.assign
来创建一个新对象(作为最佳实践,您不应该直接改变 this.state
)
新的 generateTableData()
函数只是迭代 this.state.ids
并调用 createRow
:
generateTableData() {
let res = [];
for (var i = 0; i < this.state.ids.length; i++) {
let id = this.state.ids[i];
let item = this.state.items[id];
res.push(this.createRow(item));
}
return res;
}
如您所见,this.state
中的新结构使查找 items/ids
变得容易
现在,最后一个主要变化是 createRow
,我们不再需要使用数组:
createRow(data) {
return (
<tr key={data.id}>
<td>{data.deposit_name}</td>
<td>
<input
id={data.id}
type="text"
value={data.amount}
onChange={this.handleChange}
/>
</td>
</tr>
);
}
这样,我们就有了一个完整的工作演示:
https://codesandbox.io/s/Whosebug-answer-dynamic-input-datatable-2zygh
完整代码在这里:
import { Component } from 'react';
export class Datatable extends Component {
constructor(props) {
super(props);
let tableData = this.props.snapshotData.data.deposits;
let invenstments = tableData.Investment;
let liquid = tableData.Liquid;
let savings = tableData.Savings;
let merged = [].concat(invenstments).concat(liquid).concat(savings);
let state = {
items: {},
ids: [],
};
for (var i = 0; i < merged.length; i++) {
state.items[merged[i].id] = merged[i];
state.ids.push(merged[i].id);
}
this.state = state;
this.generateHeader = this.generateHeader.bind(this);
this.generateTableData = this.generateTableData.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
let nextState = Object.assign({}, this.state);
nextState.items[event.target.id].amount = event.target.value;
this.setState(nextState);
}
generateTableData() {
let res = [];
for (var i = 0; i < this.state.ids.length; i++) {
let id = this.state.ids[i];
let item = this.state.items[id];
res.push(this.createRow(item));
}
return res;
}
generateHeader() {
const columnHeader = ['Deposit name', 'Amount'];
let res = [];
for (var i = 0; i < columnHeader.length; i++) {
res.push(<th key={columnHeader[i]}>{columnHeader[i]}</th>);
}
return res;
}
createRow(data) {
return (
<tr key={data.id}>
<td>{data.deposit_name}</td>
<td>
<input
id={data.id}
type="text"
value={data.amount}
onChange={this.handleChange}
/>
</td>
</tr>
);
}
render() {
return (
<div className="row">
<div className="col-12">
<div className="card">
<div className="card-header">
<h3 className="card-title">DataTable with default features</h3>
</div>
<div className="card-body">
<table
id="example1"
className="table table-bordered table-striped"
>
<thead>
<tr>{this.generateHeader()}</tr>
</thead>
<tbody>{this.generateTableData()}</tbody>
<tfoot>
<tr>{this.generateHeader()}</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
);
}
}
我有一个从父组件到子组件 (DataTable) 的数据集。我正在用传入的数据创建一个数据表。我能够创建数据表,但我面临 2 个问题:
- 我无法在 Datatable 的输入元素中写入内容
- 我无法根据传入的数据设置输入框的初始值
我的目标是我想为所有输入设置一些初始值(动态的,基于数据)并且用户应该能够编辑输入值。
我是 React 的新手,我无法理解这个问题
以下是我的代码:
import react, {Component} from 'react';
import $ from 'jquery';
export default class Datatable extends Component{
constructor(props){
super(props)
this.state = {
value:""
}
this.generateHeader = this.generateHeader.bind(this);
this.generateTableData = this.generateTableData.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleChange(event){
console.log("change clicked");
this.setState({value: event.target.value});
}
generateHeader(){
const columnHeader = ["Deposit name", "Amount"]
let res=[];
for(var i =0; i < columnHeader.length; i++){
res.push(<th key={columnHeader[i]}>{columnHeader[i]}</th>)
}
return res;
}
generateTableData(){
let tableData = this.props.snapshotData.data.deposits;
let invenstments = tableData.Investment;
let liquid = tableData.Liquid;
let savings = tableData.Savings;
let arr = $.merge(this.createRow(invenstments), this.createRow(liquid))
let res = $.merge(arr, this.createRow(savings));
return res;
}
createRow(data){
let res=[];
for(var i=0; i < data.length; i++){
res.push(
<tr>
<td key={data[i].name}>{data[i].deposit_name}</td>
<td key={data[i].id}><input type="text" value={this.state.value} onChange={this.handlehange} /></td>
</tr>
)
}
return res;
}
render(){
return(
<div className="row">
<div className="col-12">
<div className="card">
<div className="card-header">
<h3 className="card-title">DataTable with default features</h3>
</div>
<div className="card-body">
<table id="example1" className="table table-bordered table-striped">
<thead>
<tr>
{this.generateHeader()}
</tr>
</thead>
<tbody>
{this.generateTableData()}
</tbody>
<tfoot>
<tr>
{this.generateHeader()}
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
)
}
}
我想设置为input values的初始值是:data[i].amount in createRow(data) method.
输入json格式如下:
{
"data": {
"deposits": {
"Investment": [
{
"amount": 1000.0,
"deposit_name": "Test 12",
"id": 12
},
{
"amount": 1000.0,
"deposit_name": "Test 13",
"id": 13
}
],
"Liquid": [
{
"amount": 1000.0,
"deposit_name": "Test 3",
"id": 3
}
],
"Savings": [
{
"amount": 1000.0,
"deposit_name": "Test 1",
"id": 1
},
{
"amount": 1000.0,
"deposit_name": "Test 2",
"id": 2
}
]
}
},
"message": "success",
"status": true
}
根据您在代码中分享的详细信息,我假设 Datatable
组件的使用方式如下:
<Datatable
snapshotData={{
data: {
deposits: {
Investment: [{ amount: 0, deposit_name: "", id: "" }, ...],
Liquid: [{ amount: 0, deposit_name: "", id: "" }, ...],
Savings: [{ amount: 0, deposit_name: "", id: "" }, ...],
},
},
}}
/>
从那里开始,在不过多更改代码的情况下,我们需要确保初始状态包含正确的数据
我们会将您的逻辑从 generateTableData
移至构建阶段
这将帮助我们启动具有正确数据结构的组件:
constructor(props) {
super(props);
let tableData = this.props.snapshotData.data.deposits;
let invenstments = tableData.Investment;
let liquid = tableData.Liquid;
let savings = tableData.Savings;
let merged = [].concat(invenstments).concat(liquid).concat(savings);
let state = {
items: {},
ids: []
};
for (var i = 0; i < merged.length; i++) {
state.items[merged[i].id] = merged[i];
state.ids.push(merged[i].id);
}
this.state = state;
this.generateHeader = this.generateHeader.bind(this);
this.generateTableData = this.generateTableData.bind(this);
this.handleChange = this.handleChange.bind(this);
}
根据上面的逻辑,我们将有一个 this.state
看起来像:
this.state = {
items: {
12: {
"amount": ...,
"deposit_name": ...,
"id": ...,
},
13: {...}
},
ids: [12, 13, 3]
}
此结构帮助我们“查找和更新”this.state.items
中的值,并使用 this.state.ids
现在 handleChange
,我们需要查找正确的对象并为反应生成新状态:
handleChange(event) {
let nextState = Object.assign({}, this.state);
nextState.items[event.target.id].amount = event.target.value;
this.setState(nextState);
}
我们在这里使用 Object.assign
来创建一个新对象(作为最佳实践,您不应该直接改变 this.state
)
新的 generateTableData()
函数只是迭代 this.state.ids
并调用 createRow
:
generateTableData() {
let res = [];
for (var i = 0; i < this.state.ids.length; i++) {
let id = this.state.ids[i];
let item = this.state.items[id];
res.push(this.createRow(item));
}
return res;
}
如您所见,this.state
中的新结构使查找 items/ids
现在,最后一个主要变化是 createRow
,我们不再需要使用数组:
createRow(data) {
return (
<tr key={data.id}>
<td>{data.deposit_name}</td>
<td>
<input
id={data.id}
type="text"
value={data.amount}
onChange={this.handleChange}
/>
</td>
</tr>
);
}
这样,我们就有了一个完整的工作演示: https://codesandbox.io/s/Whosebug-answer-dynamic-input-datatable-2zygh
完整代码在这里:
import { Component } from 'react';
export class Datatable extends Component {
constructor(props) {
super(props);
let tableData = this.props.snapshotData.data.deposits;
let invenstments = tableData.Investment;
let liquid = tableData.Liquid;
let savings = tableData.Savings;
let merged = [].concat(invenstments).concat(liquid).concat(savings);
let state = {
items: {},
ids: [],
};
for (var i = 0; i < merged.length; i++) {
state.items[merged[i].id] = merged[i];
state.ids.push(merged[i].id);
}
this.state = state;
this.generateHeader = this.generateHeader.bind(this);
this.generateTableData = this.generateTableData.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
let nextState = Object.assign({}, this.state);
nextState.items[event.target.id].amount = event.target.value;
this.setState(nextState);
}
generateTableData() {
let res = [];
for (var i = 0; i < this.state.ids.length; i++) {
let id = this.state.ids[i];
let item = this.state.items[id];
res.push(this.createRow(item));
}
return res;
}
generateHeader() {
const columnHeader = ['Deposit name', 'Amount'];
let res = [];
for (var i = 0; i < columnHeader.length; i++) {
res.push(<th key={columnHeader[i]}>{columnHeader[i]}</th>);
}
return res;
}
createRow(data) {
return (
<tr key={data.id}>
<td>{data.deposit_name}</td>
<td>
<input
id={data.id}
type="text"
value={data.amount}
onChange={this.handleChange}
/>
</td>
</tr>
);
}
render() {
return (
<div className="row">
<div className="col-12">
<div className="card">
<div className="card-header">
<h3 className="card-title">DataTable with default features</h3>
</div>
<div className="card-body">
<table
id="example1"
className="table table-bordered table-striped"
>
<thead>
<tr>{this.generateHeader()}</tr>
</thead>
<tbody>{this.generateTableData()}</tbody>
<tfoot>
<tr>{this.generateHeader()}</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
);
}
}