Reactjs React/Antd:基于JSON响应的动态表单字段

Reactjs React/Antd:基于JSON响应的动态表单字段,reactjs,forms,parent-child,dynamically-generated,antd,Reactjs,Forms,Parent Child,Dynamically Generated,Antd,我试图创建一个表单,该表单基于JSON响应动态映射字段 我目前有一个虚拟对象,我正在将其设置为状态,但最后一个阶段将从外部API调用接收数据。数据集可能会随着时间的推移而变化,并根据业务需要添加或删除键/值。作为替代,我需要创建一个智能组件,它接受一组初始数据,并为对象中的每个键/值对映射一个“只读”字段 第二个问题是实际的表单布局。我在下面有一个初始的脚手架,我只硬编码了列和行。如何实现从数据响应创建两列行的逻辑 非常感谢您在这方面的任何想法/帮助 代码: import React, { Co

我试图创建一个表单,该表单基于JSON响应动态映射字段

我目前有一个虚拟对象,我正在将其设置为状态,但最后一个阶段将从外部API调用接收数据。数据集可能会随着时间的推移而变化,并根据业务需要添加或删除键/值。作为替代,我需要创建一个智能组件,它接受一组初始数据,并为对象中的每个键/值对映射一个“只读”字段

第二个问题是实际的表单布局。我在下面有一个初始的脚手架,我只硬编码了列和行。如何实现从数据响应创建两列行的逻辑

非常感谢您在这方面的任何想法/帮助

代码:

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'));
import React,{Component}来自'React';
从'react dom'导入{render};
从“antd”导入{Form,Button,Input,Row,Col};
导入“antd/dist/antd.css”;
导入“/style.css”;
类OpportunityDetails扩展组件{
构造函数(){
超级();
此.state={
残疾人:对,,
formLayout:'水平',
机会详情:[
{
客户名称:“,
字段2:“一些数据”,
字段3:“一些数据”,
字段4:“一些数据”,
字段5:“一些数据”,
字段6:“一些数据”,
字段7:“一些数据”,
字段8:“一些数据”,
字段9:“一些数据”,
字段10:“一些数据”,
字段11:“一些数据”,
字段12:“一些数据”,
字段13:“一些数据”,
字段14:“一些数据”,
字段15:“一些数据”
}
]
};
this.toggleSwitch=this.toggleSwitch.bind(this)
}
切换开关(){
this.setState(previousState=>({
已禁用:!previousState.disabled,
已启用:previousState.disabled
}))
}
modifyRoute(){
警报(“将您发送到修改楼层”);
}
上传路线(){
警报(“将您发送到上载扇区!”)
}
render(){
const{disabled}=this.state;
const{enabled}=this.state;
返回(
///按钮组
修改文档
上传文档
解锁报价
///包含所有键/值对的列和行的表单部分

{opportunityDetails.map(细节=>{
返回detail.forEach(([key,value])=>(
)
)
})}

认真对待阿米尔的评论。一旦你这么做了,你可能会重新构造你的数据,使它更方便(和可读):

我不知道为什么
opportunityDetails
必须是一个数组,但我还是适应了它。尽管它会增加复杂性,正如您所看到的

1.)这就是您希望数据的外观(稍后您将了解原因):

下面的步骤和模式是特定于JSX(或react)的;我想说的是,这是在react中呈现JSX元素的
数组的最常见方法:

2.)创建一个返回JSX数组的方法,我使用了.map,因为.forEach不起作用(您可能需要自己搜索原因)


附言:我建议掌握
.map
以及如何从方法返回jsx数组,因为在React项目中有100%的时间你会遇到相同的模式。

迭代函数有问题吗?我不太确定如何设置迭代函数来创建对象和数组上的Antd ElementSiteation没有问题与Antd或React相关的东西,这是基本的JavaScript函数。我建议你花更多的时间学习JavaScript,然后React,你将能够将所有东西应用到每个UI库、Antd、引导材料……我知道如何迭代对象,但Antd显示标题和文本的方式让我感到不舒服。我可以设置使用返回部分向上映射,如
opportunityDetails.map(key=>(
但这对Antd不起作用,因为您在实际的
组件中定义了标题和文本。这就是问题所在,映射在数组上,但在数组中有一个对象,您不能映射到对象上,您应该使用,例如,每个键,值对我们得到的数据响应在数组中。我们正在与API团队合作,让它们作为对象返回响应。我可以使用上述逻辑映射到具有嵌套对象的对象上吗?而不是像您这样的单独对象数组,作为如何构造数据的示例,例如
{itemKey:“CustomerName”,itemValue:“},{itemKey:“Field2”,itemValue:“某些数据”}
@JCalkins89是的。你试过了吗?它实际上在我这边起作用。
opportunityDetails
将成为数组数组而不是对象数组。当opportunityDetails是一个包含键/值对的单个对象数组时,它会起作用,但当我将数据更改为对象数组时,标题字段都会变成itemKey和itemValue a应该是标题的值都转移到字段中。有没有更好的方法来映射响应是否为嵌套对象的对象?我的错误与#1我可能没有充分表达我的意思。没错,我已经为您完成了转换/映射部分。如果您只还原原始的
opportunityDetails
,您将从堆栈闪电战中获得正确的结果。如果您注意到opportunityDetails…构造函数中的map函数,该函数
.map
完成了重构
opportunityDetails
<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>
/*[
   { 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]
    };
  });
})
renderDynamicElWrapper() {
  return this.state.opportunityDetails.map(items => {
    return (
      <Row type="flex" justify="space-around">
        {this.renderDynamicEl(items)}
      </Row>
    );
  });
 }
  renderDynamicEl(els) {
    return els.map(el => {
      return (
        <Col span={10}>
          <Form.Item label={el.itemKey}>
            <Input placeholder={el.itemValue} />
          </Form.Item>
        </Col>
      );
    });
  }
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>
    );
  }