antd Form组件获取子组件的值

5,531 阅读2分钟

###我的项目中的实际场景是,在antd的form中,需要抽离出许多子组件,子组件拥有不同的输入控件组合,子组件中的输入控件Form.item表单域,最终父级Form提交submit时,需要获取到子组件中的value值 代码如下:

父组件

<Form>
    ......
    <AddPortMapping title="端口映射"
        form={this.props.form}
        initIds="addPMids"
    />
    ......
</Form>

子组件

import React from 'react'

import { Form, Input, Icon, Row, Col, Button, Select } from 'antd'

import styles from './styles.scss'
const { Option } = Select

class AddPortMapping extends React.Component {
    ......
    render () {
      const { getFieldDecorator, getFieldValue } = this.props.form
      getFieldDecorator(this.props.initIds, { initialValue: [] })
      const keys = getFieldValue(this.props.initIds)
      const fromItems = keys.map((k, i) => (
        <Row key={k} style={{ marginBottom: '0' }}>
          <Col span={6}>
            <Form.Item
              key={`containerPort-${i}`}
            >
              {
                getFieldDecorator(`containerPorts[${k}]`, {
                  validateTrigger: ['onChange'],
                  rules: [
                    {
                      required: true,
                      whitespace: true,
                      message: '填写端口号'
                    }
                  ]
                })(<Input style={{ width: '100%' }}/>)
              }
            </Form.Item>
          </Col>
          <Col span={4} className={styles['smallLabel']}>
            <Form.Item
              key={`protocol-${i}`}
            >
              {
                getFieldDecorator(`protocols[${k}]`)(
                  <Select
                    showSearch
                    placeholder="Select a agreement"
                    optionFilterProp="children"
                    onChange={this.onChangeForSelect}
                    onSearch={this.onSearchForSelect}
                    filterOption={(input, option) =>
                      option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
                    }
                  >
                    <Option value="TCP">TCP</Option>
                    <Option value="UDP">UDP</Option>
                  </Select>
                )
              }
            </Form.Item>
          </Col>
          <Col span={6}>
            <Form.Item
              key={`kind-${i}`}
            >
              {
                getFieldDecorator(`kinds[${k}]`)(
                  <Select
                    showSearch
                    placeholder="Select a person"
                    optionFilterProp="children"
                    onChange={this.onChangeForSelect}
                    onSearch={this.onSearchForSelect}
                    filterOption={(input, option) =>
                      option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
                    }
                  >
                    <Option value="NodePort">NodePort(所有主机端口均可访问)</Option>
                    <Option value="HostPort">HostPort(仅Pod所在主机端口可访问)</Option>
                    <Option value="ClusterIP">集群IP(集群内部访问)</Option>
                    <Option value="LoadBalancer">L4层负载均衡器(对接公有云负载均衡服务)</Option>
                  </Select>
                )
              }
            </Form.Item>
          </Col>
          <Col span={6}>
            <Form.Item
              key={`sourcePort-${i}`}
            >
              <Select
                showSearch
                style={{ width: '30%' }}
                optionFilterProp="children"
                onChange={this.onChangeForSelect}
                filterOption={(input, option) =>
                  option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
                }
              >
                <Option value="manuallyEnter">手动输入</Option>
              </Select>
              {
                getFieldDecorator(`sourcePorts[${k}]`)(<Input style={{ width: '70%' }}></Input>)
              }
            </Form.Item>
          </Col>
          <Col span={2} className={styles['smallLabel']}>
            {
              keys.length > 0 ? (
                <Button type="primary" onClick={() => this.remove(k)}>
                  <Icon type="minus" />
                </Button>
              ) : null
            }
          </Col>
        </Row>
      ))
      return (
        <div className={styles['changeFoot']}>
          <p>{this.props.title}</p>
          <Row>
            <Col span={6}>
              <span style={{ color: 'red' }}>*</span>容器端口:
            </Col>
            <Col span={6}>协议</Col>
            <Col span={6}>网络模式</Col>
            <Col span={6}>
              <span style={{ color: 'red' }}>*</span>主机监听端口
            </Col>
          </Row>
          {fromItems}
          <Button type="primary" onClick={this.add} style={{ margin: '0' }}>
            <Icon type="plus" /> 添加规则
          </Button>
        </div>
      )
    }
}

// export default Form.create()(AddPortMapping)
export default AddPortMapping

起初为了使用this.props.form 我使用了Form.create,之后在父组件引用的时候发现父组件无法获取到子组件中的value值,最终解决办法是,子组件中的this.props.form可以直接由父组件中传入,这样在父组件的submit中,就可以获取到子组件中的控件值了,第一次这样使用antd,遇到这个问题,所以记录一下,也给同样遇到这样问题的小伙伴一点点思路,写的不好,轻喷😊