React / Antd: динамические поля формы на основе ответа JSON - PullRequest
1 голос
/ 02 апреля 2019

Я пытаюсь создать форму, которая динамически отображает поля на основе ответа 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'));

Ответы [ 2 ]

1 голос
/ 02 апреля 2019

Относитесь серьезно к комментарию Амира.И как только вы это сделаете, вы, вероятно, реструктурируете свои данные, чтобы они были более удобными (и удобочитаемыми):

Я не знаю, почему 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 (или реагируют);я пытаюсь сказать, что это самый распространенный способ рендеринга array of JSX elements в реакции:

2.) Создайте метод, который будет возвращать массив JSX , яиспользуется .map, потому что .forEach не будет работать (вы можете искать причину по своему усмотрению).

renderDynamicElWrapper() {
  return this.state.opportunityDetails.map(items => {
    return (
      <Row type="flex" justify="space-around">
        {this.renderDynamicEl(items)}
      </Row>
    );
  });
 }

при условии, что вы можете добавить в элементDetails более 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 (
      <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>
    );
  }

PS: Iсоветовал бы освоить .map и как вернуть массив jsx из метода, потому что в 100% случаев вы встретите такой же шаблон в проектах React.

0 голосов
/ 02 апреля 2019
<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>
...