Form 表单

具有数据收集、校验和提交功能的表单,包含复选框、单选框、输入框、下拉选择框等元素。

表单#

我们为 form 提供了以下两种排列方式:

  • 水平排列:可以实现 label 标签和表单控件的水平排列;
  • 行内排列:使其表现为 inline-block 级别的控件。

表单域#

表单一定会包含表单域,表单域可以是输入控件,标准表单域,标签,下拉菜单,文本域等。

这里我们分别封装了表单域 <Form.Item /> 和输入控件 <Input />

<Form.Item {...props}>
  {children}
</Form.Item>

Input 输入框#

<Input {...props} />

API#

Form#

参数 说明 类型 可选值 默认值
horizontal 水平排列布局 boolean false
inline 行内排列布局 boolean false
onSubmit 数据验证成功后回调事件 Function(e:Event)
prefixCls 样式类名,默认为 ant-form,通常您不需要设置 string 'ant-form'

Form.Item#

参数 说明 类型 可选值 默认值
label label 标签的文本 string
labelCol label 标签布局,通 <Col> 组件,设置 span offset 值,如 {span: 3, offset: 12} object
wrapperCol 需要为输入控件设置布局样式时,使用该属性,用法同 labelCol object
help 提示信息 string
required 是否必填 bool false
validateStatus 校验状态 string 'success' 'warning' 'error' 'validating'
hasFeedback 配合 validateStatus 属性使用,是否展示校验状态图标 bool false
prefixCls 样式类名,默认为 ant-form,通常您不需要设置 string 'ant-form'

Form.ValueMixin#

Mixin:当表单控件的输入值改变时,更新 formData。

你需要为每个输入控件声明 name 属性

Input#

参数 说明 类型 可选值 默认值
type 【必须】声明 input 类型,同原生 input 标签的 type 属性 string 'text'
value value 值 any
id id number 或 string
size 控件大小,默认值为 default string {'large','default','small'} 'default'
defaultValue 设置初始默认值 any
disabled 是否禁用状态,默认为 false bool false
addonBefore 带标签的 input,设置前置标签 node
addonAfter 带标签的 input,设置后置标签 node
prefixCls 样式类名前缀,默认是 ant,通常您不需要设置 string 'ant'

Input.Group#

<Input.Group className={string}>      // 样式类名前缀,默认是 ant-input-group,通常您不需要设置。
  {children}
</Input.Group>

代码演示

import {Row, Col, Input} from 'antd';
const InputGroup = Input.Group;

ReactDOM.render(
  <Row>
    <InputGroup>
      <Col span="6">
        <Input id="largeInput" size="large" placeholder="大尺寸" />
      </Col>
      <Col span="6">
        <Input id="defaultInput" placeholder="默认尺寸" />
      </Col>
      <Col span="6">
        <Input id="smallInput" placeholder="小尺寸" size="small" />
      </Col>
    </InputGroup>
  </Row>
, document.getElementById('components-form-demo-input'));

我们为 <Input /> 输入框定义了三种尺寸(大、默认、小),具体使用详见 API

注意: 在表单里面,我们只使用大尺寸, 即高度为 32px,作为唯一的尺寸。

import {Form, Input, Button, Checkbox, Radio, Row, Col, message} from 'antd';
const FormItem = Form.Item;
const RadioGroup = Radio.Group;

const Demo = React.createClass({
  mixins: [Form.ValueMixin],

  getInitialState() {
    return {
      formData: {
        userName: '大眼萌 minion',
        password: undefined,
        gender: 'male',
        remark: undefined,
        agreement: undefined,
      }
    };
  },

  handleSubmit(e) {
    e.preventDefault();
    message.success('收到表单值~~~ :' + JSON.stringify(this.state.formData, function(k, v) {
      if (typeof v === 'undefined') {
        return '';
      }
      return v;
    }));
  },

  render() {
    const formData = this.state.formData;
    return (
      <Form horizontal onSubmit={this.handleSubmit}>
        <FormItem
          label="用户名:"
          labelCol={{span: 6}}
          wrapperCol={{span: 6}}
          required>
          <p className="ant-form-text" id="userName" name="userName">大眼萌 minion</p>
        </FormItem>
        <FormItem
          id="password"
          label="密码:"
          labelCol={{span: 6}}
          wrapperCol={{span: 14}}
          required>
          <Input type="password" id="password" name="password" placeholder="请输入密码" value={formData.password} onChange={this.setValue.bind(this, 'password')} />
        </FormItem>
        <FormItem
          label="您的性别:"
          labelCol={{span: 6}}
          wrapperCol={{span: 14}}
          required>
            <RadioGroup name="gender" value={formData.gender} onChange={this.setValue.bind(this, 'gender')} >
              <Radio value="male">男的</Radio>
              <Radio value="female">女的</Radio>
            </RadioGroup>
        </FormItem>
        <FormItem
          id="remark"
          label="备注:"
          labelCol={{span: 6}}
          wrapperCol={{span: 14}}
          required
          help="随便写点什么">
          <Input type="textarea" placeholder="随便写" id="remark" name="remark" value={formData.remark} onChange={this.setValue.bind(this, 'remark')} />
        </FormItem>
        <FormItem
          wrapperCol={{span: 14, offset: 6}} >
          <label>
            <Checkbox name="agreement" value={formData.agreement} onChange={this.setValue.bind(this, 'agreement')} /> 同意
          </label>
        </FormItem>
        <Row>
          <Col span="16" offset="6">
            <Button type="primary" htmlType="submit">确定</Button>
          </Col>
        </Row>
      </Form>
    );
  }
});

ReactDOM.render(<Demo />, document.getElementById('components-form-demo-horizontal-form'));

示例展示了如何通过使用 Form.ValueMixin 来获取和更新表单提交的数值。

注意: 你需要为每个输入控件声明 name 属性。

import {Form, Input, Select, Row, Col} from 'antd';
const FormItem = Form.Item;
const InputGroup = Input.Group;
const Option = Select.Option;

ReactDOM.render(
  <Form horizontal>
    <FormItem
      label="标签输入框:"
      labelCol={{span: 6}}
      wrapperCol={{span: 16}}>
      <Input addonBefore="Http://" defaultValue="mysite.com" id="site1"/>
    </FormItem>

    <FormItem
      label="标签输入框:"
      labelCol={{span: 6}}
      wrapperCol={{span: 16}}>
      <Input addonBefore="Http://" addonAfter=".com" defaultValue="mysite" id="site2"/>
    </FormItem>

    <FormItem
      label="select 标签输入框:"
      labelCol={{span: 6}}
      wrapperCol={{span: 16}}>
      <InputGroup>
        <Input id="site4" placeholder="www.mysite" />
        <div className="ant-input-group-wrap">
          <Select defaultValue=".com" style={{width:70}}>
            <Option value=".com">.com</Option>
            <Option value=".jp">.jp</Option>
            <Option value=".cn">.cn</Option>
            <Option value=".org">.org</Option>
          </Select>
        </div>
      </InputGroup>
    </FormItem>

    <FormItem
      label="输入身份证:"
      labelCol={{span: 6}}
      wrapperCol={{span: 16}}>
      <InputGroup>
        <Col span="6">
          <Input id="certNo1" />
        </Col>
        <Col span="6">
          <Input id="certNo2" />
        </Col>
        <Col span="6">
          <Input id="certNo3" />
        </Col>
        <Col span="6">
          <Input id="certNo4" />
        </Col>
      </InputGroup>
    </FormItem>

    <FormItem
      label="电话号码:"
      labelCol={{span: 6}}
      wrapperCol={{span: 16}}>
      <Row>
        <Col span="4">
          <Input id="tel1" defaultValue="086" />
        </Col>
        <Col span="2">
          <p className="ant-form-split">--</p>
        </Col>
        <Col span="18">
          <InputGroup>
            <Col span="8">
              <Input id="tel1" />
            </Col>
            <Col span="8">
              <Input id="tel2" />
            </Col>
            <Col span="8">
              <Input id="tel3" />
            </Col>
          </InputGroup>
        </Col>
      </Row>
    </FormItem>
  </Form>

, document.getElementById('components-form-demo-input-group'));

各类输入框的组合展现。

import { Form, Input, Datepicker, Col } from 'antd';
const FormItem = Form.Item;

ReactDOM.render(
  <Form horizontal>
    <FormItem
      label="失败校验:"
      labelCol={{span: 5}}
      wrapperCol={{span: 12}}
      validateStatus="error"
      help="请输入数字和字母组合">
      <Input defaultValue="无效选择" id="error" />
    </FormItem>

    <FormItem
      label="警告校验:"
      labelCol={{span: 5}}
      wrapperCol={{span: 12}}
      validateStatus="warning">
      <Input defaultValue="前方高能预警" id="warning" />
    </FormItem>

    <FormItem
      label="校验中:"
      labelCol={{span: 5}}
      wrapperCol={{span: 12}}
      hasFeedback
      validateStatus="validating"
      help="信息审核中...">
      <Input defaultValue="我是被校验的内容" id="validating" />
    </FormItem>

    <FormItem
      label="成功校验:"
      labelCol={{span: 5}}
      wrapperCol={{span: 12}}
      hasFeedback
      validateStatus="success">
      <Input defaultValue="我是正文" id="success" />
    </FormItem>

    <FormItem
      label="警告校验:"
      labelCol={{span: 5}}
      wrapperCol={{span: 12}}
      hasFeedback
      validateStatus="warning">
      <Input defaultValue="前方高能预警" id="warning" />
    </FormItem>

    <FormItem
      label="失败校验:"
      labelCol={{span: 5}}
      wrapperCol={{span: 12}}
      hasFeedback
      validateStatus="error"
      help="请输入数字和字母组合">
      <Input defaultValue="无效选择" id="error" />
    </FormItem>

    <FormItem
      label="Datepicker:"
      labelCol={{span: 5}}
      validateStatus="error">
      <Col span="6">
        <Datepicker />
      </Col>
      <Col span="1">
        <p className="ant-form-split">-</p>
      </Col>
      <Col span="6">
        <Datepicker />
      </Col>
      <Col span="19" offset="5">
        <p className="ant-form-explain">请输入正确选项</p>
      </Col>
    </FormItem>
  </Form>
, document.getElementById('components-form-demo-validate'));

我们为表单控件定义了三种校验状态,为 <FormItem> 定义 validateStatus 属性即可。

validateStatus: ['success', 'warning', 'error', 'validating']。

另外为输入框添加反馈图标,设置 <FormItem>hasFeedback 属性值为 true 即可。

注意: 反馈图标只对 <Input /> 有效。

import {Form, Input, Button, Checkbox, message} from 'antd';
const FormItem = Form.Item;

const Demo = React.createClass({
  mixins: [Form.ValueMixin],

  getInitialState() {
    return {
      formData: {
        userName: undefined,
        password: undefined,
        agreement: undefined,
      }
    };
  },

  handleSubmit(e) {
    e.preventDefault();
    message.success('收到表单值~~~ :' + JSON.stringify(this.state.formData, function(k, v) {
      if (typeof v === 'undefined') {
        return '';
      }
      return v;
    }));
  },

  render() {
    const formData = this.state.formData;
    return (
      <Form inline onSubmit={this.handleSubmit}>
        <FormItem
          id="userName"
          label="账户:">
          <Input placeholder="请输入账户名" id="userName" name="userName" onChange={this.setValue.bind(this, 'userName')} value={formData.userName} />
        </FormItem>
        <FormItem
          id="password"
          label="密码:">
          <Input type="password" placeholder="请输入密码" id="password" name="password" onChange={this.setValue.bind(this, 'password')} value={formData.password} />
        </FormItem>
        <FormItem>
          <label className="ant-checkbox-inline">
            <Checkbox name="agreement" value={formData.agreement} onChange={this.setValue.bind(this, 'agreement')} /> 记住我
          </label>
        </FormItem>
        <Button type="primary" htmlType="submit">登录</Button>
      </Form>
    );
  }
});

ReactDOM.render(<Demo />, document.getElementById('components-form-demo-inline-form'));

行内排列,常用于登录界面。

import {Form, Input, Select, Checkbox, Radio} from 'antd';
const FormItem = Form.Item;
const Option = Select.Option;
const RadioGroup = Radio.Group;

function handleSelectChange(value) {
  console.log('selected ' + value);
}

ReactDOM.render(
  <Form horizontal>
    <FormItem
      id="control-input"
      label="输入框:"
      labelCol={{span: 6}}
      wrapperCol={{span: 14}}>
      <Input id="control-input" placeholder="Please enter..." />
    </FormItem>

    <FormItem
      id="control-textarea"
      label="文本域:"
      labelCol={{span: 6}}
      wrapperCol={{span: 14}}>
      <Input type="textarea" id="control-textarea"/>
    </FormItem>

    <FormItem
      id="select"
      label="Select 选择器:"
      labelCol={{span: 6}}
      wrapperCol={{span: 14}}>
      <Select id="select" size="large" defaultValue="lucy" style={{width:200}} onChange={handleSelectChange}>
        <Option value="jack">jack</Option>
        <Option value="lucy">lucy</Option>
        <Option value="disabled" disabled>disabled</Option>
        < Option value="yiminghe">yiminghe</Option>
      </Select>
    </FormItem>

    <FormItem
      label="Checkbox 多选框:"
      labelCol={{span: 6}}
      wrapperCol={{span: 18}} >
        <label className="ant-checkbox-vertical">
          <Checkbox />选项一
        </label>
        <label className="ant-checkbox-vertical">
          <Checkbox />选项二
        </label>
        <label className="ant-checkbox-vertical">
          <Checkbox disabled />选项三(不可选)
        </label>
    </FormItem>

    <FormItem
      label="Checkbox 多选框:"
      labelCol={{span: 6}}
      wrapperCol={{span: 18}} >
        <label className="ant-checkbox-inline">
          <Checkbox />选项一
        </label>
        <label className="ant-checkbox-inline">
          <Checkbox />选项二
        </label>
        <label className="ant-checkbox-inline">
          <Checkbox />选项三
        </label>
    </FormItem>

    <FormItem
      label="Radio 单选框:"
      labelCol={{span: 6}}
      wrapperCol={{span: 18}} >
        <RadioGroup value="b">
          <Radio value="a">A</Radio>
          <Radio value="b">B</Radio>
          <Radio value="c">C</Radio>
          <Radio value="d">D</Radio>
        </RadioGroup>
    </FormItem>
  </Form>
, document.getElementById('components-form-demo-form-controls'));

展示所有支持的表单控件。

: 输入框:只有正确设置了 type 属性的输入控件才能被赋予正确的样式。

import { Form, Select, InputNumber, Datepicker, Switch, Slider, Button, message, Row, Col } from 'antd';
const FormItem = Form.Item;
const Option = Select.Option;

const Demo = React.createClass({
  mixins: [Form.ValueMixin],

  getInitialState() {
    return {
      formData: {
        inputNumber: undefined,
        static: '唧唧复唧唧木兰当户织呀',
        switch: undefined,
        slider: undefined,
        select: undefined,
        startDate: undefined,
        endDate: undefined,
      }
    };
  },

  handleSubmit(e) {
    e.preventDefault();
    message.success('收到表单值~~~ :' + JSON.stringify(this.state.formData, function(k, v) {
      if (typeof v === 'undefined') {
        return '';
      }
      return v;
    }));
  },

  render() {
    const formData = this.state.formData;
    return (
      <Form horizontal onSubmit={this.handleSubmit} >
        <FormItem
          label="InputNumber 数字输入框:"
          labelCol={{span: 8}}
          wrapperCol={{span: 10}}
          required>
          <InputNumber size="large" min={1} max={10} style={{width:100}} defaultValue={3} name="inputNumber" onChange={this.setValue.bind(this, 'inputNumber')} value={formData.inputNumber} />
          <span className="ant-form-text"> 台机器</span>
        </FormItem>

        <FormItem
          label="我是标题:"
          labelCol={{span: 8}}
          wrapperCol={{span: 10}}
          required>
          <p className="ant-form-text" id="static" name="static">唧唧复唧唧木兰当户织呀</p>
          <p className="ant-form-text">
            <a href="#">链接文字</a>
          </p>
        </FormItem>

        <FormItem
          label="Switch 开关:"
          labelCol={{span: 8}}
          wrapperCol={{span: 10}}
          required>
          <Switch name="switch" onChange={this.setValue.bind(this, 'switch')} value={formData.switch} />
        </FormItem>

        <FormItem
          label="Slider 滑动输入条:"
          labelCol={{span: 8}}
          wrapperCol={{span: 10}}
          required>
          <Slider marks={['A', 'B', 'C', 'D', 'E', 'F', 'G']} name="slider" onChange={this.setValue.bind(this, 'slider')} />
        </FormItem>

        <FormItem
          label="Select 选择器:"
          labelCol={{span: 8}}
          wrapperCol={{span: 16}}
          required>
          <Select size="large" defaultValue="lucy" style={{width:200}} name="select" onChange={this.setValue.bind(this, 'select')} value={formData.select}>
            <Option value="jack">jack</Option>
            <Option value="lucy">lucy</Option>
            <Option value="disabled" disabled>disabled</Option>
            <Option value="yiminghe">yiminghe</Option>
          </Select>
        </FormItem>

        <FormItem
          label="Datepicker 日期选择框:"
          labelCol={{span: 8}}
          required>
          <Col span="6">
            <Datepicker name="startDate" onChange={this.setValue.bind(this, 'startDate')} value={formData.startDate} />
          </Col>
          <Col span="1">
            <p className="ant-form-split">-</p>
          </Col>
          <Col span="6">
            <Datepicker name="endDate" onChange={this.setValue.bind(this, 'endDate')} value={formData.endDate} />
          </Col>
        </FormItem>
        <Row>
          <Col span="16" offset="8">
            <Button type="primary" htmlType="submit">确定</Button>
          </Col>
        </Row>
      </Form>
    );
  }
});

ReactDOM.render(<Demo />, document.getElementById('components-form-demo-mix'));

集中营,展示和表单相关的其他 ant-design 组件。

import {Row, Col, Button, Input, Form} from 'antd';
const FormItem = Form.Item;

ReactDOM.render(
  <Form horizontal>
    <FormItem
      label="单独禁用输入框:"
      labelCol={{span:5}}
      wrapperCol={{span:12}}>
      <Input defaultValue="我是禁用的" disabled />
    </FormItem>

    <fieldset disabled>
      <legend>禁用的 fieldset</legend>
      <FormItem
        id="userName"
        label="用户名:"
        labelCol={{span:5}}
        wrapperCol={{span:12}}
        required>
        <p className="ant-form-text">大眼萌 minion</p>
      </FormItem>
      <FormItem
        id="password"
        label="密码:"
        labelCol={{span:5}}
        wrapperCol={{span:12}}
        required>
        <Input type="password" defaultValue="123456" id="password" />
      </FormItem>
      <Row>
        <Col span="12" offset="5">
          <Button htmlType="submit" type="primary">确定</Button>
        </Col>
      </Row>
    </fieldset>
  </Form>
, document.getElementById('components-form-demo-disabled'));

1) 单独为输入控件设置 disabled 属性;

2) 为 <fieldset> 设置 disabled 属性,可以禁用 <fieldset> 中包含的所有控件。