React-如何处理嵌套表格及其价值

时间:2018-09-07 05:09:22

标签: reactjs

我必须设置一种表格,该表格具有嵌套的单一表格值 基本上我需要将以下格式的数据发送到API

Payload: {"name": "The org name", "detail": "The org detail", "attributes": {"address": {"lines":[], "city":"", "state": "", "country": "India", "zip": ""}, "contacts":[{"name": "abc", "phone": "PH"}, {"name": "x", "phone": "PH"}] }}

我使用react-bootstrap来处理表单。

下面是我的表单的当前代码

constructor(props) {
    super(props);
    this.state = this.getInitialState();
  }
  getInitialState() {
    const initialState = {
      organizationForm: {
        name: '',
        detail: '',
        type: 'org',
        attributes: {
          contacts: [{
            name: '',
            phone: ''
          }],
          address: {
            lines: [],
            city: '',
            state: '',
            country: '',
            zip: ''
          }
        }
      },
      errors: {}
    };

    return initialState;
  }

handleChange(e) {
    const organizationForm = this.state.organizationForm;
    var key = e.target.name;
    var value = e.target.value;
    organizationForm[key] = value;
    this.setState({
      organizationForm
    });
  }

下面是表格的代码

  <Col className="create-content-wrap" sm={12}>
        <form className="">
          <FormGroup className="custom-form-group required row">
            <ControlLabel className="custom-form-control-label col-sm-3">
              Name
            </ControlLabel>
            <FormControl
              className="custom-form-control col-sm-9"
              type="text"
              name="name"
              value={organizationForm.name}
              onChange={this.handleChange.bind(this)}
            />
          </FormGroup>
          <FormGroup className="custom-form-group required row">
            <ControlLabel className="custom-form-control-label col-sm-3">
              Detail
            </ControlLabel>
            <FormControl
              className="custom-form-control col-sm-9"
              type="text"
              name="detail"
              componentClass="textarea"
              value={organizationForm.detail}
              onChange={this.handleChange.bind(this)}
            />
          </FormGroup>
          <FormGroup className="custom-form-group row">
            <ControlLabel className="custom-form-control-label col-sm-3">
              Address
            </ControlLabel>
            <FormControl
              className="custom-form-control col-sm-9"
              type="text"
              name="lines"
              componentClass="textarea"
              value={organizationForm.lines}
              onChange={this.handleAddressChange.bind(this)}
            />
          </FormGroup>
          <FormGroup className="custom-form-group row">
            <ControlLabel className="custom-form-control-label col-sm-3">
              City
            </ControlLabel>
            <FormControl
                className="custom-form-control col-sm-9"
                type="text"
                name="city"
                value={organizationForm.attributes.address.city}
                onChange={this.handleAddressChange.bind(this)}
            />
          </FormGroup>
          <FormGroup className="custom-form-group row">
            <ControlLabel className="custom-form-control-label col-sm-3">
              State
            </ControlLabel>
            <FormControl
              className="custom-form-control col-sm-9"
              type="text"
              name="state"
              value={organizationForm.attributes.address.state}
              onChange={this.handleAddressChange.bind(this)}
            />
          </FormGroup>
          <FormGroup className="custom-form-group row">
            <ControlLabel className="custom-form-control-label col-sm-3">
              Country
            </ControlLabel>
            <FormControl
              className="custom-form-control col-sm-9"
              type="text"
              name="country"
              value={organizationForm.attributes.address.country}
              onChange={this.handleAddressChange.bind(this)}
            />
          </FormGroup>
          <FormGroup className="custom-form-group row">
            <ControlLabel className="custom-form-control-label col-sm-3">
              Zipcode
            </ControlLabel>
            <FormControl
              className="custom-form-control col-sm-9"
              type="number"
              name="zip"
              value={organizationForm.attributes.address.zip}
              onChange={this.handleAddressChange.bind(this)}
            />
          </FormGroup>
          <FormGroup className="custom-form-group row">
            <ControlLabel className="custom-form-control-label col-sm-3">
              Contacts
            </ControlLabel>
            <FormControl
              className="custom-form-control col-sm-9"
              type="number"
              name="contacts"
              value={organizationForm.attributes.contacts}
              onChange={this.handleChange.bind(this)}
            />
          </FormGroup>
        </form>
      </Col>

我是React js世界中的noobie。如何绑定地址和联系人的嵌套字段?

3 个答案:

答案 0 :(得分:4)

您可以添加一些方法来处理地址和属性,如下所示 方式-1

<FormControl
      className="custom-form-control col-sm-9"
      type="text"
      name="city"
      value={organizationForm.attributes.address.city}
      onChange={this.handleAddressChange(this)}
 />

handleAddressChange = (e) => {
    const organizationForm = this.state.organizationForm;
    let address = organizationForm.attributes.address;
    var key = e.target.name;
    var value = e.target.value;
    address[key] = value;
    organizationForm.attributes.address = address;
    this.setState({
      organizationForm
    });
  }

这样,您的表单也可以松散地耦合在一起。因此,如果子对象发生任何更改,则不会影响另一个对象。同样,您可以为所有嵌套对象添加地址,属性等。

方法-2

您可以在下面执行相同的操作,但是您需要以相同的方法处理要修改的对象。

<FormControl
          className="custom-form-control col-sm-9"
          type="text"
          name="city"
          value={organizationForm.attributes.address.city}
          onChange={event => { this.handleChange(event, this.state.organizationForm.attributes.address  ,'address'); }}
     />

     <FormControl
          className="custom-form-control col-sm-9"
          type="text"
          name="city"
          value={organizationForm.attributes.address.city}
          onChange={event => { this.handleChange(event, this.state.organizationForm.attributes.contacts  ,'contacts'); }}
     />


     <FormControl
          className="custom-form-control col-sm-9"
          type="text"
          name="city"
          value=onChange={event => { this.handleChange(event, this.state.organizationForm ,'organizationForm'); }}
     />


    handleChange = (e , object , type) => {
        const organizationForm = this.state.organizationForm;
        var key = e.target.name;
        var value = e.target.value;
        object[key] = value;
        if(type === 'address'){
            organizationForm.attributes.address = object;
        } else if (type === 'contacts'){
            organizationForm.attributes.contacts = object;
        } 
        this.setState({
          organizationForm : organizationForm
        });
      }

答案 1 :(得分:1)

我建议您将组件状态保持平坦,对于表单中的每个字段只需一个键。提交表单时,可以将其格式化为API所需的形状。

答案 2 :(得分:0)

这可能不适用于所有情况,但它对我有用,并且可能对现在搜索此内容的任何人都有帮助。我有一个呈现不同输入元素的表单,但它也呈现了一个按钮,该按钮打开了一个模态组件,其中的表单与围绕它的较大表单无关。为了解决这个嵌套表单的问题:首先,我删除了模态中的表单元素(<input>),只留下了组件中的 onChange = {e => setValue(e.target.value)}。然后,在该元素中,我添加了:

const [value, setValue] = useState("");

在此之后,我创建了一个如下所示的状态变量:onClick={handleSubmit}。最后,我在输入下添加了一个类似 value 的按钮,并定义了一个函数,将 {{1}} 作为表单提交的结果提交表单。

基本上,我用 React 状态替换了嵌套表单的内部状态,移除了表单元素并保留了输入,然后创建了一个按钮来处理我的提交。这样,我绕过了嵌套表单,只使用输入元素而不是完整表单。