React/Antd:基于 JSON 响应的动态表单字段
React/Antd: Dynamic form fields based on JSON response
我正在尝试创建一个基于 JSON 响应动态映射字段的表单。
我目前有一个正在设置状态的虚拟对象,但最后阶段将从外部 API 调用接收数据。数据集可能会随时间变化,根据业务需要添加或删除 key/values。取而代之的是,我需要创建一个智能组件,该组件采用一组初始数据并为对象中的每个 key/value 对映射一个 "Read-only" 字段。
第二个问题是实际的表单布局。我在下面有一个初始脚手架,我只对列和行进行了硬编码。我如何实现从数据响应中创建两列行的逻辑?
非常感谢任何thoughts/help!
代码:
import React, { Component } from 'react';
import { render } from 'react-dom';
import { Form, Button, Input, Row, Col } from 'antd';
import "antd/dist/antd.css";
import './style.css';
class OpportunityDetails extends Component {
constructor() {
super();
this.state = {
disabled: true,
formLayout: 'horizontal',
opportunityDetails: [
{
CustomerName: "",
Field2: "Some data",
Field3: "Some data",
Field4: "Some data",
Field5: "Some data",
Field6: "Some data",
Field7: "Some data",
Field8: "Some data",
Field9: "Some data",
Field10: "Some data",
Field11: "Some data",
Field12: "Some data",
Field13: "Some data",
Field14: "Some data",
Field15: "Some data"
}
]
};
this.toggleSwitch = this.toggleSwitch.bind(this)
}
toggleSwitch() {
this.setState(previousState => ({
disabled: !previousState.disabled,
enabled: previousState.disabled
}))
}
modifyRoute(){
alert("Sending you to the modify floor");
}
uploadRoute(){
alert("Sending you to the upload sector!")
}
render() {
const { disabled } = this.state;
const { enabled } = this.state;
return (
<div className={}>
/// Button Group
<Row type="flex" justify="space-around">
<Col span={4}>
<Button disabled={disabled} onClick={this.modifyRoute}>Modify Docs</Button>
</Col>
<Col span={4}>
<Button disabled={disabled} onClick={this.uploadRoute}>Upload Docs</Button>
</Col>
<Col span={4}>
<Button disabled={enabled} onClick={this.toggleSwitch}>
Unlock Quote
</Button>
</Col>
</Row>
/// Form section with columns and rows for all key/value pairs
<Row type="flex" justify="space-around">
<Col span={10}>
<Form.Item label={key}>
<Input placeholder={value} />
</Form.Item>
</Col>
<Col span={10}>
<Form.Item label={key}>
<Input placeholder="{value} />
</Form.Item>
</Col>
</Row>
<Row type="flex" justify="space-around">
<Col span={10}>
<Form.Item label={key}>
<Input placeholder={value} />
</Form.Item>
</Col>
<Col span={10}>
<Form.Item label={key}>
<Input placeholder={value} />
</Form.Item>
</Col>
</Row>
<Row type="flex" justify="space-around">
<Col span={10}>
<Form.Item label={key}>
<Input placeholder={value} />
</Form.Item>
</Col>
<Col span={10}>
<Form.Item label={key}>
<Input placeholder={value} />
</Form.Item>
</Col>
</Row>
<Row type="flex" justify="space-around">
<Col span={10}>
<Form.Item label={key}>
<Input placeholder={value} />
</Form.Item>
</Col>
<Col span={10}>
<Form.Item label={key}>
<Input placeholder={value} />
</Form.Item>
</Col>
</Row>
</div>
);
}
}
render(<OpportunityDetails />, document.getElementById('root'));
<Row type="flex" justify="space-around">
<Col span={10}>
{opportunityDetails.map(detail=>{
return detail.forEach(([key,value])=>(
<Form.Item label={key}>
<Input placeholder={value} />
</Form.Item>
)
)
})}
</Col>
</Row>
认真对待阿米尔的评论。一旦你这样做了,你可能会重组你的数据,这样它会更方便(和可读):
我不知道为什么opportunityDetails
必须是数组,反正我已经适应了。虽然它会增加复杂性,如您所见
1.) 这就是您希望数据的样子(稍后您会明白为什么):
/*[
{ itemKey: "CustomerName", itemValue: "" },
{ itemKey: "Field2", itemValue: "Some data" }
.... and so on
]*/
opportunityDetails: [
{
CustomerName: "",
Field2: "Some data",
Field3: "Some data",
Field4: "Some data",
Field5: "Some data",
Field6: "Some data",
Field7: "Some data",
Field8: "Some data",
Field9: "Some data",
Field10: "Some data",
Field11: "Some data",
Field12: "Some data",
Field13: "Some data",
Field14: "Some data",
Field15: "Some data"
}
].map(obj => {
const objKeys = Object.keys(obj);
return objKeys.map(itemKey => {
return {
itemKey,
itemValue: obj[itemKey]
};
});
})
以下步骤和模式是 JSX(或 React)特定的;我想说的是这是在反应中呈现 array of JSX elements
的最常见方式:
2.) 创建一个方法,它将 return 一个 JSX 数组 ,我使用 .map 因为 .forEach 不起作用(你可能想搜索为什么靠你自己)。
renderDynamicElWrapper() {
return this.state.opportunityDetails.map(items => {
return (
<Row type="flex" justify="space-around">
{this.renderDynamicEl(items)}
</Row>
);
});
}
假设 opportunityDetails 将有超过 1 个项目,我们需要有另一种类似于上面的方法和迭代
renderDynamicEl(els) {
return els.map(el => {
return (
<Col span={10}>
<Form.Item label={el.itemKey}>
<Input placeholder={el.itemValue} />
</Form.Item>
</Col>
);
});
}
3.) 最后,下面是 render
方法的 return 的样子:
return (
<div>
<Row type="flex" justify="space-around">
<Col span={4}>
<Button disabled={disabled} onClick={this.modifyRoute}>
Modify Docs
</Button>
</Col>
<Col span={4}>
<Button disabled={disabled} onClick={this.uploadRoute}>
Upload Docs
</Button>
</Col>
<Col span={4}>
<Button disabled={enabled} onClick={this.toggleSwitch}>
Unlock Quote
</Button>
</Col>
</Row>
{this.renderDynamicElWrapper()}
</div>
);
}
P.S:我建议掌握 .map
以及如何从方法中 return 一个 jsx 数组,因为 %100 的时间你会在 React 中遇到相同的模式项目。
我正在尝试创建一个基于 JSON 响应动态映射字段的表单。
我目前有一个正在设置状态的虚拟对象,但最后阶段将从外部 API 调用接收数据。数据集可能会随时间变化,根据业务需要添加或删除 key/values。取而代之的是,我需要创建一个智能组件,该组件采用一组初始数据并为对象中的每个 key/value 对映射一个 "Read-only" 字段。
第二个问题是实际的表单布局。我在下面有一个初始脚手架,我只对列和行进行了硬编码。我如何实现从数据响应中创建两列行的逻辑?
非常感谢任何thoughts/help!
代码:
import React, { Component } from 'react';
import { render } from 'react-dom';
import { Form, Button, Input, Row, Col } from 'antd';
import "antd/dist/antd.css";
import './style.css';
class OpportunityDetails extends Component {
constructor() {
super();
this.state = {
disabled: true,
formLayout: 'horizontal',
opportunityDetails: [
{
CustomerName: "",
Field2: "Some data",
Field3: "Some data",
Field4: "Some data",
Field5: "Some data",
Field6: "Some data",
Field7: "Some data",
Field8: "Some data",
Field9: "Some data",
Field10: "Some data",
Field11: "Some data",
Field12: "Some data",
Field13: "Some data",
Field14: "Some data",
Field15: "Some data"
}
]
};
this.toggleSwitch = this.toggleSwitch.bind(this)
}
toggleSwitch() {
this.setState(previousState => ({
disabled: !previousState.disabled,
enabled: previousState.disabled
}))
}
modifyRoute(){
alert("Sending you to the modify floor");
}
uploadRoute(){
alert("Sending you to the upload sector!")
}
render() {
const { disabled } = this.state;
const { enabled } = this.state;
return (
<div className={}>
/// Button Group
<Row type="flex" justify="space-around">
<Col span={4}>
<Button disabled={disabled} onClick={this.modifyRoute}>Modify Docs</Button>
</Col>
<Col span={4}>
<Button disabled={disabled} onClick={this.uploadRoute}>Upload Docs</Button>
</Col>
<Col span={4}>
<Button disabled={enabled} onClick={this.toggleSwitch}>
Unlock Quote
</Button>
</Col>
</Row>
/// Form section with columns and rows for all key/value pairs
<Row type="flex" justify="space-around">
<Col span={10}>
<Form.Item label={key}>
<Input placeholder={value} />
</Form.Item>
</Col>
<Col span={10}>
<Form.Item label={key}>
<Input placeholder="{value} />
</Form.Item>
</Col>
</Row>
<Row type="flex" justify="space-around">
<Col span={10}>
<Form.Item label={key}>
<Input placeholder={value} />
</Form.Item>
</Col>
<Col span={10}>
<Form.Item label={key}>
<Input placeholder={value} />
</Form.Item>
</Col>
</Row>
<Row type="flex" justify="space-around">
<Col span={10}>
<Form.Item label={key}>
<Input placeholder={value} />
</Form.Item>
</Col>
<Col span={10}>
<Form.Item label={key}>
<Input placeholder={value} />
</Form.Item>
</Col>
</Row>
<Row type="flex" justify="space-around">
<Col span={10}>
<Form.Item label={key}>
<Input placeholder={value} />
</Form.Item>
</Col>
<Col span={10}>
<Form.Item label={key}>
<Input placeholder={value} />
</Form.Item>
</Col>
</Row>
</div>
);
}
}
render(<OpportunityDetails />, document.getElementById('root'));
<Row type="flex" justify="space-around">
<Col span={10}>
{opportunityDetails.map(detail=>{
return detail.forEach(([key,value])=>(
<Form.Item label={key}>
<Input placeholder={value} />
</Form.Item>
)
)
})}
</Col>
</Row>
认真对待阿米尔的评论。一旦你这样做了,你可能会重组你的数据,这样它会更方便(和可读):
我不知道为什么opportunityDetails
必须是数组,反正我已经适应了。虽然它会增加复杂性,如您所见
1.) 这就是您希望数据的样子(稍后您会明白为什么):
/*[
{ itemKey: "CustomerName", itemValue: "" },
{ itemKey: "Field2", itemValue: "Some data" }
.... and so on
]*/
opportunityDetails: [
{
CustomerName: "",
Field2: "Some data",
Field3: "Some data",
Field4: "Some data",
Field5: "Some data",
Field6: "Some data",
Field7: "Some data",
Field8: "Some data",
Field9: "Some data",
Field10: "Some data",
Field11: "Some data",
Field12: "Some data",
Field13: "Some data",
Field14: "Some data",
Field15: "Some data"
}
].map(obj => {
const objKeys = Object.keys(obj);
return objKeys.map(itemKey => {
return {
itemKey,
itemValue: obj[itemKey]
};
});
})
以下步骤和模式是 JSX(或 React)特定的;我想说的是这是在反应中呈现 array of JSX elements
的最常见方式:
2.) 创建一个方法,它将 return 一个 JSX 数组 ,我使用 .map 因为 .forEach 不起作用(你可能想搜索为什么靠你自己)。
renderDynamicElWrapper() {
return this.state.opportunityDetails.map(items => {
return (
<Row type="flex" justify="space-around">
{this.renderDynamicEl(items)}
</Row>
);
});
}
假设 opportunityDetails 将有超过 1 个项目,我们需要有另一种类似于上面的方法和迭代
renderDynamicEl(els) {
return els.map(el => {
return (
<Col span={10}>
<Form.Item label={el.itemKey}>
<Input placeholder={el.itemValue} />
</Form.Item>
</Col>
);
});
}
3.) 最后,下面是 render
方法的 return 的样子:
return (
<div>
<Row type="flex" justify="space-around">
<Col span={4}>
<Button disabled={disabled} onClick={this.modifyRoute}>
Modify Docs
</Button>
</Col>
<Col span={4}>
<Button disabled={disabled} onClick={this.uploadRoute}>
Upload Docs
</Button>
</Col>
<Col span={4}>
<Button disabled={enabled} onClick={this.toggleSwitch}>
Unlock Quote
</Button>
</Col>
</Row>
{this.renderDynamicElWrapper()}
</div>
);
}
P.S:我建议掌握 .map
以及如何从方法中 return 一个 jsx 数组,因为 %100 的时间你会在 React 中遇到相同的模式项目。