Form  表单

开发指南#

何时使用#

表单布局、校验、数据提交操作时用到。 组件的设计思想可以看这篇文章 https://zhuanlan.zhihu.com/p/56280821

注意事项#

API#

Fixed Name

something
import { Form, Input, Checkbox } from '@alifd/next';


const FormItem = Form.Item;

const formItemLayout = {
    labelCol: {
        fixedSpan: 10
    },
    wrapperCol: {
        span: 14
    }
};

class Demo extends React.Component {

    handleSubmit = (values) => {
        console.log('Get form value:', values);
    };

    render() {
        return (
            <Form style={{width: '60%'}} {...formItemLayout} >
                <FormItem label="baseUsername:">
                    <p>Fixed Name</p>
                </FormItem>
                <FormItem label="password:">
                    <Input htmlType="password" name="basePass" placeholder="Please Enter Password"/>
                </FormItem>
                <FormItem label="Note:" help="something">
                    <Input.TextArea placeholder="something" name="baseRemark" />
                </FormItem>
                <FormItem label="Agreement:">
                    <Checkbox name="baseAgreement" defaultChecked>Agree</Checkbox>
                </FormItem>
                <FormItem label=" ">
                    <Form.Submit onClick={this.handleSubmit}>Confirm</Form.Submit>
                </FormItem>
            </Form>
        );
    }
}

ReactDOM.render(<Demo />, mountNode);

拉伸浏览器的时候label宽度不变。

如果组件比较靠上,可以用 className="next-form-text-align" 做调整

code collapse
import { Form, Input } from '@alifd/next';


const FormItem = Form.Item;

const formItemLayout = {
    labelCol: { fixedSpan: 3 },
    wrapperCol: { span: 20 }
};

class Demo extends React.Component {
    state = {
        code: '',
        second: 60
    }

    handleSubmit = (values, errors) => {
        if (errors) {
            return;
        }
        console.log('Get form value:', values);
    };

    sendCode = (values, errors) => {
        if (errors) {
            return;
        }
        this.setState({
            code: Math.floor(Math.random() * (999999 - 99999 + 1) + 99999)
        });

        setInterval(() => {
            this.setState({
                second: --this.state.second
            });
        }, 1000);
    }

    render() {
        const { code } = this.state;

        return (
            <Form style={{ width: 400 }} {...formItemLayout} labelTextAlign="left" size="large" labelAlign="inset" >
                <FormItem label="name" required asterisk={false}>
                    <Input name="username" trim defaultValue="frank" />
                </FormItem>
                <FormItem label="phone" format="tel" required asterisk={false}>
                    <Input name="phone" trim innerAfter={
                        <Form.Submit
                            text
                            type="primary"
                            disabled={!!code}
                            validate={['phone']}
                            onClick={this.sendCode}
                            style={{ marginRight: 10 }}
                        >
                            {code ? `retry after ${this.state.second}s` : 'send code'}
                        </Form.Submit>
                    } />
                </FormItem>
                {
                    this.state.code ? <FormItem label="code" required asterisk={false}>
                        <Input name="code" trim defaultValue={this.state.code} />
                    </FormItem> : null
                }

                <FormItem label=" ">
                    <Form.Submit style={{ width: '100%' }} type="primary" validate onClick={this.handleSubmit}>Submit</Form.Submit>
                </FormItem>
            </Form>
        );
    }
}

ReactDOM.render(<Demo />, mountNode);

验证码获取

code collapse
import { Form, Input } from '@alifd/next';


const FormItem = Form.Item;

function handleSubmit(v) {
    console.log(v);
}

ReactDOM.render(<div>
    <Form inline>
        <FormItem label="Username:">
            <FormItem >
                <Input name="first" style={{width: 80}} placeholder="first"/>
            </FormItem>
            <FormItem >
                <Input name="second" style={{width: 80}} placeholder="second"/>
            </FormItem>
        </FormItem>
        <FormItem label="Password:" required hasFeedback={false}>
            <Input htmlType="password" name="inlinePass" placeholder="Please enter your password!"/>
        </FormItem>

        <FormItem label=" ">
            <Form.Submit onClick={handleSubmit}>Submit</Form.Submit>
        </FormItem>
    </Form>
</div>, mountNode);
code collapse


import { Form, Input, Select } from '@alifd/next';


const FormItem = Form.Item;
const Option = Select.Option;
const formItemLayout = {
    labelCol: {span: 4},
    wrapperCol: {span: 20}
};

class Demo extends React.Component {
    state = {
        size: 'medium'
    }

    handleChange = (v) => {
        this.setState({
            size: v
        });
    }

    render() {
        return (
            <div>
                <Form {...formItemLayout} size={this.state.size} style={{maxWidth: '500px'}}>
                    <FormItem label="Size:">
                        <Select value={this.state.size} onChange={this.handleChange} style={{width: '100%'}}>
                            <Option value="small">small</Option>
                            <Option value="medium">medium</Option>
                            <Option value="large">large</Option>
                        </Select>
                    </FormItem>
                    <FormItem label="Account:">
                        <Input placeholder="Please enter your user name" id="userName" name="userName"/>
                    </FormItem>
                    <FormItem required label="Password:">
                        <Input htmlType="password" placeholder="Please enter your password" id="password" name="password"/>
                    </FormItem>
                    <FormItem label="Password:" validateState="error">
                        <Input htmlType="password" placeholder="Check your password" id="rePass" name="rePass"/>
                    </FormItem>
                </Form>

                <br/><br/>

                <Form size={this.state.size} inline>
                    <FormItem label="Size:">
                        <Select style={{width: '100%'}} value={this.state.size} onChange={this.handleChange}>
                            <Option value="small">small</Option>
                            <Option value="medium">medium</Option>
                            <Option value="large">large</Option>
                        </Select>
                    </FormItem>
                    <FormItem label="Account:">
                        <Input placeholder="Please enter your user name" id="userName2" name="userName2"/>
                    </FormItem>
                    <FormItem label="Password:">
                        <Input htmlType="password" placeholder="Please enter your password" id="password2" name="password2"/>
                    </FormItem>
                    <FormItem label="Password:" validateState="error">
                        <Input htmlType="password" placeholder="Check your password" id="rePass2" name="rePass2"/>
                    </FormItem>
                </Form>
            </div>
        );
    }
}

ReactDOM.render(<Demo />, mountNode);
.demo-ctl {
  background-color: #f1f1f1;
  padding: 10.0px;
  color: #0a7ac3;
  border-left: 4.0px solid #0d599a;
}

size 会强制设置 FormItem 下的所有组件的size

labelAlign label方位

labelTextAlign 文字左右对齐方式

code collapse
import { Form, Input, Select } from '@alifd/next';


const FormItem = Form.Item;
const Option = Select.Option;

class Demo extends React.Component {
    render() {
        return (
            <div>
                <Form labelAlign="top" >
                    <FormItem label="Account:">
                        <Input placeholder="Please enter your user name" id="userName" name="userName"/>
                    </FormItem>

                    <FormItem required label="Password:">
                        <Input htmlType="password" placeholder="Please enter your password" id="password" name="password"/>
                    </FormItem>

                    <FormItem label="Password:" validateState="error">
                        <Input htmlType="password" placeholder="Please enter your password" id="rePass" name="rePass"/>
                    </FormItem>

                    <FormItem label="Size:">
                        <Select style={{width: '100%'}} name="size">
                            <Option value="small">small</Option>
                            <Option value="medium">medium</Option>
                            <Option value="large">large</Option>
                        </Select>
                    </FormItem>
                </Form>

                <Form inline labelAlign="top">
                    <FormItem label="Account:">
                        <Input placeholder="Please enter your user name" id="userName2" name="userName2"/>
                    </FormItem>
                    <FormItem label="Password:">
                        <Input htmlType="password" placeholder="Please enter your password" id="password2" name="password2"/>
                    </FormItem>
                    <FormItem label="Password:" validateState="error">
                        <Input htmlType="password" placeholder="Please enter your password" id="rePass2" name="rePass2"/>
                    </FormItem>
                    <FormItem label="Size:">
                        <Select style={{width: '100%'}} name="size2">
                            <Option value="small">small</Option>
                            <Option value="medium">medium</Option>
                            <Option value="large">large</Option>
                        </Select>
                    </FormItem>
                </Form>
            </div>
        );
    }
}

ReactDOM.render(<Demo />, mountNode);
.demo-ctl {
  background-color: #f1f1f1;
  padding: 10.0px;
  color: #0a7ac3;
  border-left: 4.0px solid #0d599a;
}

size 会强制设置 FormItem 下的所有组件的size

labelAlign label方位

labelTextAlign 文字左右对齐方式

code collapse


Password is required!
import { Form, Input, Select } from '@alifd/next';


const FormItem = Form.Item;
const Option = Select.Option;

const formItemLayout = {
    labelCol: {fixedSpan: 4},
    wrapperCol: {span: 20}
};

ReactDOM.render(<div>

    <Form {...formItemLayout} labelAlign="inset" style={{maxWidth: '500px'}}>
        <FormItem label="User Name:">
            <Input placeholder="Please enter your name" id="insetUserName" name="insetUserName"/>
        </FormItem>
        <FormItem label="Password:" validateState="error">
            <Input htmlType="password" placeholder="Please enter your password" id="insetPassword" name="insetPassword"/>
        </FormItem>

        <FormItem label="Size:">
            <Select style={{width: '100%'}}>
                <Option value="small">small</Option>
                <Option value="medium">medium</Option>
                <Option value="large">large</Option>
            </Select>
        </FormItem>
    </Form>

    <br/><br/>

    <Form labelAlign="inset" inline>
        <FormItem label="User Name:">
            <Input placeholder="Enter your name" id="insetUserName2" name="insetUserName2"/>
        </FormItem>
        <FormItem label="Password:" validateState="error" help="Password is required!">
            <Input htmlType="password" placeholder="Enter your password" id="insetPassword2" name="insetPassword2"/>
        </FormItem>

        <FormItem label="Size:">
            <Select style={{width: 150}}>
                <Option value="small">small</Option>
                <Option value="medium">medium</Option>
                <Option value="large">large</Option>
            </Select>
        </FormItem>
    </Form>
</div>, mountNode);

通过设置labelAlign="inset" (只适用于Input、Select组件,其他组件不适用)

code collapse
import { Form, Input, Grid } from '@alifd/next';



const FormItem = Form.Item;
const {Row, Col} = Grid;

const formItemLayout = {
    labelCol: {span: 4},
    wrapperCol: {span: 14}
};

const insetLayout = {
    labelCol: {fixedSpan: 3}
};

ReactDOM.render(<Form {...formItemLayout}>
    <FormItem id="control-input" label="Input Something:">
        <Row gutter="4">
            <Col>
                <FormItem label="Nest" labelAlign="inset" {...insetLayout} required requiredTrigger="onBlur" asterisk={false}>
                    <Input placeholder="Please enter..." name="firstname"/>
                </FormItem>
            </Col>
            <Col>
                <FormItem label="Nest" labelAlign="inset" {...insetLayout} required asterisk={false}>
                    <Input placeholder="need onChange" name="secondname" />
                </FormItem>
            </Col>
        </Row>
    </FormItem>
    <FormItem label="Bank Account:" >
        <Row gutter="4">
            <Col>
                <FormItem required requiredTrigger="onBlur">
                    <Input name="A"/>
                </FormItem>
            </Col>
            <Col>
                <FormItem required requiredTrigger="onBlur">
                    <Input name="B"/>
                </FormItem>
            </Col>
            <Col>
                <FormItem required requiredTrigger="onBlur">
                    <Input name="C"/>
                </FormItem>
            </Col>
            <Col>
                <FormItem required requiredTrigger="onBlur">
                    <Input name="D"/>
                </FormItem>
            </Col>
        </Row>
    </FormItem>
    <FormItem label=" ">
        <Form.Submit onClick={(v) => console.log(v)}>Submit</Form.Submit>
    </FormItem>
</Form>, mountNode);

FormItem 嵌套

code collapse

Label Position

top
import { Form, Input, Switch, Grid, Button, Icon, Balloon } from '@alifd/next';


const FormItem = Form.Item;
const {Row, Col} = Grid;

const style = {
    padding: '20px',
    background: '#F7F8FA',
    margin: '20px'
};
const formItemLayout = {
    labelCol: {fixedSpan: 4}
};
const label = (<span>
name:<Balloon type="primary" trigger={<Icon type="prompt" size="small" />} closable={false}>blablablablablablablabla</Balloon>
</span>);

class Demo extends React.Component {
    state = {
        labelAlign: 'top'
    }
    handleChange = (v) => {
        this.setState({
            labelAlign: v ? 'left' : 'top'
        });
    }
    render() {
        const labelAlign = this.state.labelAlign;

        return (
            <div>
                <h3>Label Position</h3>
                <Switch checkedChildren="left" unCheckedChildren="top" checked={this.state.labelAlign === 'left'} onChange={this.handleChange} />

                <Form style={style}>
                    <Row gutter="4">
                        <Col>
                            <FormItem {...formItemLayout} labelAlign={labelAlign}
                                label={label}
                                required
                            >
                                <Input placeholder="Enter a search name:"/>
                            </FormItem>
                            <FormItem {...formItemLayout} labelAlign={labelAlign}
                                label="Long search name:"
                            >
                                <Input placeholder="Enter a search name:"/>
                            </FormItem>
                            <FormItem {...formItemLayout} labelAlign={labelAlign}
                                label="Search name:"
                            >
                                <Input placeholder="Enter a search name:"/>
                            </FormItem>
                        </Col>
                        <Col>
                            <FormItem {...formItemLayout} labelAlign={labelAlign}
                                label="Search name:"
                            >
                                <Input placeholder="Enter a search name:"/>
                            </FormItem>
                            <FormItem {...formItemLayout} labelAlign={labelAlign}
                                label="Long search name:"
                            >
                                <Input placeholder="Enter a search name:"/>
                            </FormItem>
                            <FormItem {...formItemLayout} labelAlign={labelAlign}
                                label="Search name:"
                            >
                                <Input placeholder="Enter a search name:"/>
                            </FormItem>
                        </Col>
                        <Col>
                            <FormItem {...formItemLayout} labelAlign={labelAlign}
                                label="Search name:"
                            >
                                <Input placeholder="Enter a search name:"/>
                            </FormItem>
                            <FormItem {...formItemLayout} labelAlign={labelAlign}
                                label="Long search name:"
                            >
                                <Input placeholder="Enter a search name:"/>
                            </FormItem>
                            <FormItem {...formItemLayout} labelAlign={labelAlign}
                                label="Search name:"
                            >
                                <Input placeholder="Enter a search name:"/>
                            </FormItem>
                        </Col>
                    </Row>
                    <Row>
                        <Col style={{ textAlign: 'right' }}>
                            <Button type="primary" style={{ marginRight: '5px' }}>Search</Button>
                            <Button >Clear All</Button>
                        </Col>
                    </Row>
                </Form>


                <Form style={style}>
                    <Row gutter="4">
                        <Col>
                            <FormItem {...formItemLayout} labelAlign={labelAlign}
                                label={label}
                                required
                            >
                                <Input placeholder="Enter a search name:"/>
                            </FormItem>
                        </Col>
                        <Col>
                            <FormItem {...formItemLayout} labelAlign={labelAlign}
                                label="Long search name:"
                            >
                                <Input placeholder="Enter a search name:"/>
                            </FormItem>
                        </Col>
                        <Col>
                            <FormItem {...formItemLayout} labelAlign={labelAlign}
                                label="Search name:"
                            >
                                <Input placeholder="Enter a search name:"/>
                            </FormItem>
                        </Col>
                        <Col>
                            <FormItem {...formItemLayout} labelAlign={labelAlign}
                                label="Search name:"
                            >
                                <Input placeholder="Enter a search name:"/>
                            </FormItem>
                        </Col>
                        <Col>
                            <FormItem {...formItemLayout} labelAlign={labelAlign}
                                label="Search name:"
                            >
                                <Input placeholder="Enter a search name:"/>
                            </FormItem>
                        </Col>
                    </Row>
                    <Row>
                        <Col style={{ textAlign: 'right' }}>
                            <Button type="primary" style={{ marginRight: '5px' }}>Search</Button>
                            <Button >Clear All</Button>
                        </Col>
                    </Row>
                </Form>
            </div>
        );
    }
}

ReactDOM.render(<Demo />, mountNode);

标签位置:上、左

配合 Row Col 控制表单内元素布局 (注意:FormItem非Form直接子元素需要不能直接直接在Form上设置布局)

code collapse

Label Position

top
import { Form, Input, Switch, Grid, Button, Icon, Balloon, ResponsiveGrid, ConfigProvider, Box } from '@alifd/next';

const FormItem = Form.Item;
const {Row, Col} = Grid;

const style = {
    padding: '20px',
    background: '#F7F8FA',
    margin: '20px'
};
const formItemLayout = {
    labelWidth: 100,
    colSpan: 4,
};

const label = (<span>
name:<Balloon type="primary" trigger={<Icon type="prompt" size="small" />} closable={false}>blablablablablablablabla</Balloon>
</span>);

class Demo extends React.Component {
    state = {
        labelAlign: 'top',
        device: 'desktop'
    }
    handleChange = (v) => {
        this.setState({
            labelAlign: v ? 'left' : 'top'
        });
    }
    btn = (device) => {
        this.setState({
            device
        });
    }
    render() {
        const labelAlign = this.state.labelAlign;

        return (
            <ConfigProvider device={this.state.device}>
                <div>
                    <h3>Label Position</h3>
                    <Switch checkedChildren="left" unCheckedChildren="top" checked={this.state.labelAlign === 'left'} onChange={this.handleChange} />
                    <Button onClick={this.btn.bind(this,'desktop')}>desktop</Button>
                    <Button onClick={this.btn.bind(this,'tablet')}>tablet</Button>
                    <Button onClick={this.btn.bind(this,'phone')}>phone</Button>

                    <Form style={style} responsive>
                        <FormItem {...formItemLayout} labelAlign={labelAlign}
                            label={label}
                            required
                        >
                            <Input placeholder="Enter a search name:"/>
                        </FormItem>
                        <FormItem {...formItemLayout} labelAlign={labelAlign}
                            label="Long search name:"
                        >
                            <Input placeholder="Enter a search name:"/>
                        </FormItem>
                        <FormItem {...formItemLayout} labelAlign={labelAlign}
                            label="Search name:"
                        >
                            <Input placeholder="Enter a search name:"/>
                        </FormItem>
                        <FormItem {...formItemLayout} labelAlign={labelAlign}
                            label="Search name:"
                        >
                            <Input placeholder="Enter a search name:"/>
                        </FormItem>
                        <FormItem {...formItemLayout} labelAlign={labelAlign}
                            label="Long search name:"
                        >
                            <Input placeholder="Enter a search name:"/>
                        </FormItem>
                        <FormItem {...formItemLayout} labelAlign={labelAlign}
                            label="Search name:"
                        >
                            <Input placeholder="Enter a search name:"/>
                        </FormItem>
                        <FormItem {...formItemLayout} labelAlign={labelAlign}
                            label="Search name:"
                        >
                            <Input placeholder="Enter a search name:"/>
                        </FormItem>
                        <FormItem {...formItemLayout} labelAlign={labelAlign}
                            label="Long search name:"
                        >
                            <Input placeholder="Enter a search name:"/>
                        </FormItem>
                        <FormItem {...formItemLayout} labelAlign={labelAlign}
                            label="Search name:"
                        >
                            <Input placeholder="Enter a search name:"/>
                        </FormItem>
                        <FormItem colSpan={12} style={{ textAlign: 'right' }}>
                            <Button type="primary" style={{ marginRight: '5px' }}>Search</Button>
                            <Button >Clear All</Button>
                        </FormItem>
                    </Form>
                </div>
            </ConfigProvider>
        );
    }
}

ReactDOM.render(<Demo />, mountNode);

可通过设置 device responsive 实现响应式, 1.19.0+ 添加,仅支持ie10+

code collapse
import { Form, Input } from '@alifd/next';


const FormItem = Form.Item;

class Demo extends React.Component {
    onSubmit(e) {
        e.preventDefault(); // form will auto submit if remove this line
        console.log('onsubmit');
    }

    render() {
        return (
            <Form onSubmit={this.onSubmit.bind(this)}>
                <FormItem >
                    <Input placeholder="Enter Key can also trigger ‘onSubmit’"/>
                </FormItem>
                <Form.Submit htmlType="submit">submit</Form.Submit>
            </Form>
        );
    }
}

ReactDOM.render(<Demo />, mountNode);

需要Form里面有 htmlType="submit" 的元素

code collapse
something
import { Form, Input, Select } from '@alifd/next';

const FormItem = Form.Item;

const formItemLayout = {
    labelCol: {xxs: 4, l: 4},
    wrapperCol: {xxs: 20, l: 16}
};

ReactDOM.render(<Form {...formItemLayout} >
    <FormItem label="userName:">
        <Input />
    </FormItem>
    <FormItem label="password:">
        <Input htmlType="password" name="resPass" placeholder="Please Enter Password"/>
    </FormItem>
    <FormItem label="Country:">
        <Select placeholder="Please select a country" style={{width: '100%'}}>
            <option value="china">China</option>
            <option value="use">United States</option>
            <option value="japan">Japan</option>
            <option value="korean">South Korea</option>
            <option value="Thailand">Thailand</option>
        </Select>
    </FormItem>
    <FormItem label="Note:" help="something">
        <Input.TextArea placeholder="something" name="resReremark" />
    </FormItem>
    <FormItem label=" ">
        <Form.Submit>Submit</Form.Submit>
    </FormItem>
</Form>, mountNode);

可以通过配置 labelCol wrapperColGrid.Col 响应式属性实现响应式

code collapse
Please enter a numeric and alphabetic string
Information Checking...
Please select the correct date
Please select the correct time
Please select a country
import { Form, Input, DatePicker, TimePicker, NumberPicker, Select } from '@alifd/next';


const FormItem = Form.Item;

const formItemLayout = {
    labelCol: {
        span: 6
    },
    wrapperCol: {
        span: 14
    }
};

ReactDOM.render(
    <Form {...formItemLayout}>
        <FormItem label="Input Error:" validateState="error" help="Please enter a numeric and alphabetic string">
            <Input defaultValue="Invalid choice"/>
        </FormItem>

        <FormItem label="Loading:" hasFeedback validateState="loading" help="Information Checking...">
            <Input defaultValue="Checking"/>
        </FormItem>

        <FormItem label="Success:" hasFeedback validateState="success">
            <Input defaultValue="Successful verification"/>
        </FormItem>

        <FormItem label="Datepicker:" validateState="error" help="Please select the correct date">
            <DatePicker />
        </FormItem>

        <FormItem label="Timepicker:" validateState="error" help="Please select the correct time">
            <TimePicker />
        </FormItem>

        <FormItem label="Select:" validateState="error" help="Please select a country">
            <Select placeholder="Please select a country">
                <option value="china">China</option>
                <option value="use">United States</option>
                <option value="japan">Japan</option>
                <option value="korean">South Korea</option>
                <option value="Thailand">Thailand</option>
            </Select>
        </FormItem>

        <FormItem label="NumberPicker:" validateState="error">
            <NumberPicker defaultValue={0} />
        </FormItem>
    </Form>
    , mountNode);

<FormItem> 定义 state 属性控制三种校验状态。

如果是 <Input> 组件, 可在<FormItem>上面添加 hasFeedback 控制图标的展示

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

code collapse
import { Form, Input, Field } from '@alifd/next';


const FormItem = Form.Item;

const formItemLayout = {
    labelCol: {
        span: 6
    },
    wrapperCol: {
        span: 14
    }
};

class BasicDemo extends React.Component {
    field = new Field(this);

    render() {
        const {
            field,
            field: {
                init,
            }
        } = this;
        return (
            <Form {...formItemLayout} field={field} >

                <Form.Item label="test" key="test2">
                    <Input  {...init('input', {
                    rules: [{
                        validator(_rule, value, callback) {
                        callback(<span>This is a <em>CUSTOM</em> error</span>);
                        }
                    }]
                    })}  />
                </Form.Item>
                <FormItem wrapperCol={{ offset: 6 }} >
                    <Form.Submit validate type="primary">Submit</Form.Submit>
                    <Form.Reset >Reset</Form.Reset>
                </FormItem>
            </Form>
        );
    }
}

ReactDOM.render(<BasicDemo />, mountNode);

基本的表单校验例子。

code collapse
0/20
import { Form, Input, Radio } from '@alifd/next';


const FormItem = Form.Item;
const RadioGroup = Radio.Group;

const formItemLayout = {
    labelCol: {
        span: 6
    },
    wrapperCol: {
        span: 14
    }
};

class BasicDemo extends React.Component {
    userExists(rule, value) {
        return new Promise((resolve, reject) => {
            if (!value) {
                resolve();
            } else {
                setTimeout(() => {
                    if (value === 'frank') {
                        reject([new Error('Sorry, this username is already exist.')]);
                    } else {
                        resolve();
                    }
                }, 500);
            }
        });
    }

    render() {
        return (
            <Form {...formItemLayout} >
                <FormItem
                    label="Account:"
                    hasFeedback
                    validator={this.userExists.bind(this)}
                    help=""
                >
                    <Input placeholder="Input frank" name="valUsername" />
                    <Form.Error name="valUsername" >{
                        (errors, state) => {
                            if (state === 'loading') {
                                return 'loading...';
                            } else {
                                return errors;
                            }
                        }
                    }</Form.Error>
                </FormItem>
                <FormItem
                    label="Email:"
                    hasFeedback
                    required
                    requiredTrigger="onBlur"
                    format="email"
                >
                    <Input placeholder="Both trigget onBlur and onChange" name="valEmail" />
                </FormItem>

                <FormItem
                    label="Password:"
                    hasFeedback
                    required
                    requiredMessage="Please enter password"
                >
                    <Input htmlType="password" name="valPasswd" />
                </FormItem>

                <FormItem
                    label="Gender:"
                    hasFeedback
                    required
                    requiredMessage="Please select your gender"
                >
                    <RadioGroup name="valSex" >
                        <Radio value="male">Male</Radio>
                        <Radio value="female">Female</Radio>
                    </RadioGroup>
                </FormItem>

                <FormItem
                    label="Remarks:"
                    required
                    requiredMessage="Really do not intend to write anything?"
                >
                    <Input.TextArea maxLength={20} hasLimitHint placeholder="Everything is ok!" name="valTextarea" />
                </FormItem>

                <FormItem wrapperCol={{ offset: 6 }} >
                    <Form.Submit validate type="primary" onClick={(v, e) => console.log(v, e)} style={{marginRight: 10}}>Submit</Form.Submit>
                    <Form.Reset >Reset</Form.Reset>
                </FormItem>
            </Form>
        );
    }
}

ReactDOM.render(<BasicDemo />, mountNode);

基本的表单校验例子。

code collapse

Hello

import { Form, Input, Radio, Field, Button } from '@alifd/next';


const FormItem = Form.Item;
const RadioGroup = Radio.Group;

const formItemLayout = {
    labelCol: {
        span: 6
    },
    wrapperCol: {
        span: 14
    }
};

class BasicDemo extends React.Component {
    field = new Field(this);

    userExists(rule, value) {
        return new Promise((resolve, reject) => {
            if (!value) {
                resolve();
            } else {
                setTimeout(() => {
                    if (value === 'frank') {
                        reject([new Error('Sorry, this username is already occupied.')]);
                    } else {
                        resolve();
                    }
                }, 500);
            }
        });
    }

    checkPass(rule, value, callback) {
        const { validate } = this.field;
        if (value) {
            validate(['rePasswd']);
        }
        callback();
    }

    checkPass2(rule, value, callback) {
        const { getValue } = this.field;
        if (value && value !== getValue('passwd')) {
            return callback('Inconsistent password input twice!');
        } else {
            return callback();
        }
    }

    validate = () => {
        this.field.validate(['sex']);
    }

    render() {
        const {getState, getValue, getError} = this.field;

        return (
            <Form {...formItemLayout} field={this.field}>
                <FormItem
                    label="Username:"
                    hasFeedback
                    required
                    validator={this.userExists.bind(this)}
                    help={getState('username') === 'loading' ? 'Checking ...' : getError('username')}
                >
                    <Input placeholder="Input frank" name="username" />
                    <p>Hello {getValue('username')}</p>
                </FormItem>

                <FormItem
                    label="Password:"
                    hasFeedback
                    required
                    requiredMessage="Please enter password"
                    validator={this.checkPass.bind(this)}
                >
                    <Input htmlType="password" name="passwd" />
                </FormItem>

                <FormItem
                    label="Check your password:"
                    hasFeedback
                    required
                    requiredMessage="Enter your password again"
                    validator={this.checkPass2.bind(this)}
                >
                    <Input htmlType="password" placeholder="Enter the same password twice" name="rePasswd" />
                </FormItem>

                <FormItem
                    label="Gender:"
                    hasFeedback
                    required
                    requiredMessage="Please select your gender"
                >
                    <RadioGroup name="sex" >
                        <Radio value="male">Male</Radio>
                        <Radio value="female">Female</Radio>
                    </RadioGroup>
                </FormItem>

                <FormItem wrapperCol={{ offset: 6 }} >
                    <Button onClick={this.validate}>Validate by Field</Button>
                    <Form.Submit validate type="primary" onClick={(v, e) => console.log(v, e)} style={{margin: '0 10px'}}>Submit</Form.Submit>
                    <Form.Reset >Reset</Form.Reset>
                </FormItem>
            </Form>
        );
    }
}


ReactDOM.render(<BasicDemo />, mountNode);

配合 Field 可以实现较复杂功能

code collapse

The quick brown fox jumps over the lazy dog.

Link

Something in here
0100
import { Form, Input, Button, Checkbox, Radio, Select, Range, Balloon, DatePicker, TimePicker, NumberPicker, Field, Switch, Upload, Grid } from '@alifd/next';



const FormItem = Form.Item;
const Option = Select.Option;
const RangePicker = DatePicker.RangePicker;
const {Row, Col} = Grid;

const formItemLayout = {
    labelCol: {span: 6},
    wrapperCol: {span: 14}
};

class Demo extends React.Component {
    field = new Field(this);

    handleSubmit(value) {
        console.log('Form values:', value);
    }

    render() {
        const init = this.field.init;

        return (
            <Form {...formItemLayout} field={this.field}>
                <FormItem label="I'm the title:">
                    <p className="next-form-text-align">The quick brown fox jumps over the lazy dog.</p>
                    <p ><a href="#">Link</a></p>
                </FormItem>

                <FormItem label="Password:">
                    <Balloon trigger={<Input htmlType="password" {...init('pass')} />} align="r" closable={false} triggerType="hover">
                        input password
                    </Balloon>
                </FormItem>

                <FormItem label="NumberPicker:">
                    <NumberPicker min={1} max={10} name="numberPicker" defaultValue={3} />
                    <span>Something in here</span>
                </FormItem>

                <FormItem
                    label="Switch:"
                    required>
                    <Switch name="switch" defaultChecked />
                </FormItem>

                <FormItem label="Range:" required>
                    <Range defaultValue={30} scales={[0, 100]} marks={[0, 100]} name="range" />
                </FormItem>

                <FormItem label="Select:" required>
                    <Select style={{width: 200}} name="select">
                        <Option value="jack">jack</Option>
                        <Option value="lucy">lucy</Option>
                        <Option value="disabled" disabled>disabled</Option>
                        <Option value="hugohua">hugohua</Option>
                    </Select>
                </FormItem>

                <FormItem
                    label="DatePicker:"
                    labelCol={{span: 6}}
                    required>
                    <Row>
                        <FormItem style={{marginRight: 10, marginBottom: 0}}><DatePicker name="startDate"/></FormItem>
                        <FormItem style={{marginBottom: 0}}><DatePicker name="endDate" /></FormItem>
                    </Row>
                </FormItem>

                <FormItem
                    label="RangePicker:"
                    labelCol={{span: 6}}
                    required>
                    <RangePicker name="rangeDate"/>
                </FormItem>

                <FormItem
                    label="TimePicker:"
                    required>
                    <TimePicker name="time" />
                </FormItem>

                <FormItem
                    label="Checkbox:">
                    <Checkbox.Group name="checkbox">
                        <Checkbox value="a">option 1 </Checkbox>
                        <Checkbox value="b">option 2 </Checkbox>
                        <Checkbox disabled value="c">option 3(disabled)</Checkbox>
                    </Checkbox.Group>
                </FormItem>

                <FormItem
                    label="Radio:">
                    <Radio.Group name="radio">
                        <Radio value="apple">apple</Radio>
                        <Radio value="banana">banana</Radio>
                        <Radio disabled value="cherry">cherry(disabled)</Radio>
                    </Radio.Group>
                </FormItem>

                <FormItem
                    label="Logo:"
                >
                    <Upload action="/upload.do" listType="text" name="upload" >
                        <Button type="primary" style={{margin: '0 0 10px'}}>Upload</Button>
                    </Upload>
                </FormItem>
                <Row style={{marginTop: 24}}>
                    <Col offset="6">
                        <Form.Submit type="primary" onClick={this.handleSubmit.bind(this)}>Submit</Form.Submit>
                    </Col>
                </Row>
            </Form>
        );
    }
}

ReactDOM.render(<Demo />, mountNode);

展示和表单相关的其他组件。

code collapse

email:

import { Form, Input, Button, Checkbox, Field } from '@alifd/next';
import { combineReducers, createStore } from 'redux';
import { Provider, connect } from 'react-redux';




const CheckboxGroup = Checkbox.Group;
function formReducer(state = {email: '', username: 'xiachi', fruit: ['apple']}, action) {
    switch (action.type) {
        case 'save_fields':
            return {
                ...state,
                ...action.payload
            };
        default:
            return state;
    }
}

class FormDemo extends React.Component {
    constructor(props) {
        super(props);
        this.field = new Field(this, {
            onChange: (name, value) => {
                console.log('onChange', name, value, this.field.getValues());
                this.props.dispatch({
                    type: 'save_fields',
                    payload: {
                        [name]: value
                    }
                });
                /* Method 2, Updates all values.
                 this.props.dispatch({
                 type: 'save_fields',
                 payload: this.field.getValues()
                 });
                 */
            }
        });
    }

    componentWillReceiveProps(nextProps) {
        this.field.setValues(nextProps.formData);
    }

    setEmail() {
        this.props.dispatch({
            type: 'save_fields',
            payload: {
                email: 'qq@gmail.com'
            }
        });
    }

    setName() {
        this.props.dispatch({
            type: 'save_fields',
            payload: {
                username: 'frank'
            }
        });
    }

    setGroup() {
        this.props.dispatch({
            type: 'save_fields',
            payload: {
                fruit: ['pear']
            }
        });
    }

    render() {
        return (<Form field={this.field}>
            <Form.Item required requiredMessage="required!">
                <Input name="email"/>
            </Form.Item>
            <Form.Item required requiredMessage="required!">
                <Input name="username" defaultValue={this.props.formData.username} />
            </Form.Item>
            <Form.Item required requiredMessage="required!">
                <CheckboxGroup name="fruit" dataSource={[{label: 'Apple', value: 'apple'}, {label: 'Pear', value: 'pear'}]} defaultValue={this.props.formData.fruit}/>
            </Form.Item>

            <p>email: {this.props.email && this.props.email.value}</p>
            <Button onClick={this.setEmail.bind(this)}>setEmail</Button>
            <Button onClick={this.setName.bind(this)}>setName</Button>
            <Button onClick={this.setGroup.bind(this)}>setGroup</Button>
        </Form>);
    }
}

const ReduxFormDemo = connect((state) => {
    return {
        formData: state.formReducer
    };
})(FormDemo);

const store = createStore(combineReducers({
    formReducer
}));

ReactDOM.render(<Provider store={store}>
    <div>
        <ReduxFormDemo />
    </div>
</Provider>, mountNode);

redux中结合 componentWillReceiveProps setValues 使用, 配合 Field 使用

code collapse

email:

import { Form, Input, Button, Field } from '@alifd/next';
import { combineReducers, createStore } from 'redux';
import { Provider, connect } from 'react-redux';



const initState = {
    values: {email: '', username: 'xiachi'},
    errors: {}
};

function formReducer(state = initState, action) {
    switch (action.type) {
        case 'save_fields':
            return {
                ...state,
                values: {
                    ...state.values,
                    ...action.values
                }
            };
        case 'set_errors':
            return {
                ...state,
                errors: {
                    ...state.errors,
                    ...action.errors
                }
            };
        default:
            return state;
    }
}

class FormDemo extends React.Component {
    constructor(props) {
        super(props);

        this.field = new Field(this, {
            onChange: (name, value) => {
                console.log('onChange', name, value, this.field.getError(name));
                this.props.dispatch({
                    type: 'save_fields',
                    values: {
                        [name]: value
                    }
                });
                this.props.dispatch({
                    type: 'set_errors',
                    errors: {
                        [name]: this.field.getError(name)
                    }
                });
            }
        });
    }

    componentWillReceiveProps(nextProps) {
        this.field.setValues(nextProps.formData.values);
        this.field.setErrors(nextProps.formData.errors);
    }

    setEmail() {
        this.props.dispatch({
            type: 'save_fields',
            values: {
                email: 'qq@gmail.com'
            }
        });
    }

    setName() {
        this.props.dispatch({
            type: 'save_fields',
            values: {
                username: 'frank'
            }
        });
    }

    setError() {
        this.props.dispatch({
            type: 'set_errors',
            errors: {
                email: 'Error message from remote'
            }
        });
    }

    setErrors() {
        this.props.dispatch({
            type: 'set_errors',
            errors: {
                email: 'A-Error message from remote',
                username: 'B-Error message from remote'
            }
        });
    }

    render() {
        return (<Form field={this.field}>
            <Form.Item required format="email">
                <Input name="email"/>
            </Form.Item>
            <Form.Item help="" required requiredMessage="required">
                <Input name="username" defaultValue={this.props.formData.values.username} />
                <p style={{color: 'blue'}}>{this.field.getError('username')}</p>
            </Form.Item>

            <p>email: {this.props.email && this.props.email.value}</p>
            <Button onClick={this.setEmail.bind(this)}>setEmail</Button>
            <Button onClick={this.setName.bind(this)}>setName</Button>
            <Button onClick={this.setError.bind(this)}>setError</Button>
            <Button onClick={this.setErrors.bind(this)}>setErrors</Button>
            <Button onClick={() => this.field.reset()}>reset</Button>
        </Form>);
    }
}


const ReduxFormDemo = connect((state) => {
    return {
        formData: state.formReducer
    };
})(FormDemo);

const store = createStore(combineReducers({
    formReducer
}));

ReactDOM.render(<Provider store={store}>
    <div>
        <ReduxFormDemo />
    </div>
</Provider>, mountNode);

redux中结合 componentWillReceiveProps setErrors 使用, 配合 Field 使用更加方便

如果需要自己控制错误位置,可以让help="" 然后自己放置展示错误的地方

code collapse
上传图片
import { Form, Input, Select, Radio, Checkbox, DatePicker, Switch, Upload, Grid, Field } from '@alifd/next';

const RadioGroup = Radio.Group;
const {Row, Col} = Grid;
const FormItem = Form.Item;
const Option = Select.Option;
const formItemLayout = {
    labelCol: {
        span: 7
    },
    wrapperCol: {
        span: 16
    }
};
class Demo extends React.Component {
    state = {
        size: 'medium'
    };
    submitHandle = (e) => {
        console.log(e);
    };
    render() {
        return (
            <div>
                <Form {...formItemLayout} size={this.state.size} style={{maxWidth: '800px'}}>
                    <FormItem required label="username:">
                        <Input placeholder="Please enter your username" id="a11yUsername" name="a11yUsername" aria-required="true"   />
                    </FormItem>
                    <FormItem required label="Password:">
                        <Input htmlType="password" placeholder="Please enter your password" id="a11yPassword" name="a11yPassword" aria-required="true" />
                    </FormItem>
                    <FormItem  
                        id="myDateInput-1"
                        required
                        label="Accessible Date 1 (YYYY/MM/DD):"
                        requiredMessage="Please select your date"
                    >
                        <DatePicker name="a11yDate" format="YYYY/MM/DD" inputProps={{"aria-required": "true", "id": "myDateInput-1"}}/> 
                    </FormItem>
                    <FormItem  
                        required
                        label="Accessible Date 2 (YYYY/MM/DD):"
                        requiredMessage="Please select your date"
                    >
                        <DatePicker name="a11yOtherDate" format="YYYY/MM/DD" dateInputAriaLabel="Date input format YYYY/MM/DD" inputProps={{"aria-required": "true", "aria-label": "Accessible Date 2"}}/> 
                    </FormItem>
                    <FormItem label="Switch:">
                        <Switch name="a11ySwitch" aria-label="Accessible Switch" defaultChecked/>
                    </FormItem>
                    <FormItem
                        required
                        label="gender:"
                        requiredMessage="Please select your gender"
                    >
                        <RadioGroup name="a11ySex">
                            <Radio value="male" aria-required="true">Male</Radio>
                            <Radio value="female" aria-required="true">Female</Radio>
                        </RadioGroup>
                    </FormItem>
                    <FormItem label="Language:">
                        <Checkbox.Group name="a11yLangs" aria-label="Please select a programming language">
                            <Checkbox value="python">python</Checkbox>
                            <Checkbox value="java">java</Checkbox>
                            <Checkbox value="angular">angular</Checkbox>
                            <Checkbox value="c">c</Checkbox>
                            <Checkbox value="other">other</Checkbox>
                        </Checkbox.Group>
                    </FormItem>
                    <FormItem label="upload:">
                        <Upload.Card
                            listType="card"
                            action="https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload"
                            accept="image/png, image/jpg, image/jpeg, image/gif, image/bmp"
                            defaultValue={[]}
                            limit={2}
                            name="a11yUpload"
                        />
                    </FormItem>
                    <FormItem label="Note:">
                        <Input.TextArea placeholder="description" name="a11yRemark"/>
                    </FormItem>
                    <FormItem wrapperCol={{offset: 5}}>
                        <Form.Submit validate type="primary" onClick={this.submitHandle} style={{marginRight: 7}}>Submit</Form.Submit>
                        <Form.Reset style={{marginLeft: 130}}>Reset</Form.Reset>
                    </FormItem>
                </Form>
            </div>
        );
    }
}
ReactDOM.render(<Demo />, mountNode);

对于必填项,在组件中要设置aria-required属性,并通过视觉设计上的高亮提示用户。

code collapse

Fixed Name

something
import { Form, Input, Checkbox, Switch, Radio } from '@alifd/next';


const FormItem = Form.Item;

const formItemLayout = {
    labelCol: {
        fixedSpan: 10
    },
    wrapperCol: {
        span: 14
    }
};

class Demo extends React.Component {
    state = {
        device: 'desktop'
    }

    handleDeviceChange = (device) => {
        this.setState({
            device
        });
    };

    render() {
        return (
            <div>
                <Radio.Group
                    shape="button"
                    value={this.state.device}
                    onChange={this.handleDeviceChange}
                >
                    <Radio value="desktop">desktop</Radio>
                    <Radio value="phone">phone</Radio>
                </Radio.Group>
                <hr/>
                <Form style={{width: '60%'}} {...formItemLayout} device={this.state.device}>
                    <FormItem label="Username:">
                        <p>Fixed Name</p>
                    </FormItem>
                    <FormItem label="password:">
                        <Input htmlType="password" name="basePass" placeholder="Please Enter Password"/>
                    </FormItem>
                    <FormItem label="Note:" help="something">
                        <Input.TextArea placeholder="something" name="baseRemark" />
                    </FormItem>
                    <FormItem label="Agreement:">
                        <Checkbox name="baseAgreement" defaultChecked>Agree</Checkbox>
                    </FormItem>
                    <FormItem label=" ">
                        <Form.Submit >Confirm</Form.Submit>
                    </FormItem>
                </Form>
            </div>
        );
    }
}

ReactDOM.render(<Demo />, mountNode);

device=phone 下会强制设置 labelAlign=top

code collapse
http://.com
import { Form, Input, Switch, Rating, Field, Icon, Radio, Range, Checkbox, NumberPicker, Select, Upload } from '@alifd/next';

const FormItem = Form.Item;
const formItemLayout = {
    labelCol: {
        span: 7
    },
    wrapperCol: {
        span: 16
    }
};
const fileList = [{
    uid: '0',
    name: 'IMG.png',
    state: 'done',
    url: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
    downloadURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
    imgURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg'
}, {
    uid: '1',
    name: 'IMG.png',
    percent: 50,
    state: 'uploading',
    url: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
    downloadURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
    imgURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg'
}, {
    uid: '2',
    name: 'IMG.png',
    state: 'error',
    url: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
    downloadURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
    imgURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg'
}];

class Demo extends React.Component {
    state = {
        size: 'medium',
        preview: false,
    };
    submitHandler = (e) => {
        console.log(e);
    };
    onPreviewChange = (checked) => {
        this.setState({
            preview: checked
        });
    };
    ratingPreview = (value) => {
        return <p>{value} {value > 2.5 ? <Icon type="smile" /> : <Icon type="cry"/>}</p>;
    };
    render() {
        return (
            <div>
                <Form {...formItemLayout} isPreview={this.state.preview} size={this.state.size} style={{maxWidth: '800px'}}>
                    <FormItem label="preview: " isPreview={false} size="small" style={{marginBottom: 0}}>
                        <Switch size="large" onChange={this.onPreviewChange} />
                    </FormItem>
                    <div style={{height: 1, width: '100%', margin: '20px 0'}}/>
                    <FormItem required label="Username:">
                        <Input defaultValue="Fusion" placeholder="Please enter your username" id="username" name="username" aria-required="true"   />
                    </FormItem>
                    <FormItem required label="Password:">
                        <Input defaultValue="Fusion@2019" htmlType="password" placeholder="Please enter your password" id="password" name="password" aria-required="true" />
                    </FormItem>

                    <FormItem required label="Link:">
                        <Input name="link" addonTextBefore="http://" addonTextAfter=".com" defaultValue="alibaba" aria-label="input with config of addonTextBefore and addonTextAfter" />
                    </FormItem>

                    <FormItem required label="Number:">
                        <NumberPicker name="number" defaultValue={1} />
                    </FormItem>

                    <FormItem required label="autoComplete:">
                        <Select.AutoComplete name="autoComplete" defaultValue="selected" />
                    </FormItem>

                    <FormItem required label="multiple Select:">
                        <Select name="select" defaultValue={["apple", "banana"]} mode="multiple" >
                            <Select.Option value="apple">Apple</Select.Option>
                            <Select.Option value="banana">Banana</Select.Option>
                        </Select>
                    </FormItem>

                    <FormItem required label="Rating:">
                        <Rating defaultValue={4.5} name="rate" aria-label="what's the rate score" />
                    </FormItem>

                    <FormItem required label="Custom Render Rating:" renderPreview={this.ratingPreview}>
                        <Rating defaultValue={4.5} name="rate2" aria-label="what's the rate2 score" />
                    </FormItem>

                    <FormItem required label="Checkbox:">
                        <Checkbox.Group name="checkbox" defaultValue={['react', 'vue']}>
                            <Checkbox value="react">React</Checkbox>
                            <Checkbox value="vue">Vue</Checkbox>
                            <Checkbox value="angular">Angular</Checkbox>
                        </Checkbox.Group>
                    </FormItem>

                    <FormItem required label="Radio:">
                        <Radio.Group name="radio" defaultValue={'react'} >
                            <Radio value="react">React</Radio>
                            <Radio value="vue">Vue</Radio>
                            <Radio value="angular">Angular</Radio>
                        </Radio.Group>
                    </FormItem>

                    <FormItem required label="Range:">
                        <Range name="range" slider="double" defaultValue={[10, 80]} />
                    </FormItem>

                    <FormItem label="Note:">
                        <Input.TextArea placeholder="description" name="a11yRemark" defaultValue="Fusion 是一套企业级中后台UI的解决方案,致力于解决设计师与前端在产品体验一致性、工作协同、开发效率方面的问题。通过协助业务线构建设计系统,提供系统化工具协助设计师前端使用设计系统,下游提供一站式设计项目协作平台;打通互联网产品从设计到开发的工作流。" />
                    </FormItem>

                    <FormItem label="Upload:">
                        <Upload name="upload" defaultValue={fileList} listType="text" />
                    </FormItem>
                    <FormItem label="Upload:">
                        <Upload name="upload2" defaultValue={fileList} listType="image" />
                    </FormItem>
                    <FormItem wrapperCol={{offset: 7}}>
                        <Form.Submit validate type="primary" onClick={this.submitHandler}>Submit</Form.Submit>
                        <Form.Reset style={{marginLeft: 10}}>Reset</Form.Reset>
                    </FormItem>
                </Form>
            </div>
        );
    }
}
ReactDOM.render(<Demo />, mountNode);

可以通过Form切换表单元素的预览态,切换前后布局结构相同

code collapse

# API

Form#

参数 说明 类型 默认值
inline 内联表单 Boolean -
size 单个 Item 的 size 自定义,优先级高于 Form 的 size, 并且当组件与 Item 一起使用时,组件自身设置 size 属性无效。

可选值:
'large'(大)
'medium'(中)
'small'(小)
Enum 'medium'
fullWidth 单个 Item 中表单类组件宽度是否是100% Boolean -
labelAlign 标签的位置

可选值:
'top'(上)
'left'(左)
'inset'(内)
Enum 'left'
labelTextAlign 标签的左右对齐方式

可选值:
'left'(左)
'right'(右)
Enum -
field field 实例, 传 false 会禁用 field any -
saveField 保存 Form 自动生成的 field 对象

签名:
Function() => void
Function func.noop
labelCol 控制第一级 Item 的 labelCol Object -
wrapperCol 控制第一级 Item 的 wrapperCol Object -
onSubmit form内有 htmlType="submit" 的元素的时候会触发

签名:
Function() => void
Function function preventDefault(e) { e.preventDefault(); }
children 子元素 any -
value 表单数值 Object -
onChange 表单变化回调

签名:
Function(values: Object, item: Object) => void
参数:
values: {Object} 表单数据
item: {Object} 详细
item.name: {String} 变化的组件名
item.value: {String} 变化的数据
item.field: {Object} field 实例
Function func.noop
component 设置标签类型 String/Function 'form'
device 预设屏幕宽度

可选值:
'phone', 'tablet', 'desktop'
Enum 'desktop'
responsive 是否开启内置的响应式布局 (使用ResponsiveGrid) Boolean -
isPreview 是否开启预览态 Boolean -

Form.Item#

手动传递了 wrapCol labelCol 会使用 Grid 辅助布局; labelAlign='top' 会强制禁用 Grid

参数 说明 类型 默认值
label label 标签的文本 ReactNode -
size 单个 Item 的 size 自定义,优先级高于 Form 的 size, 并且当组件与 Item 一起使用时,组件自身设置 size 属性无效。

可选值:
'large', 'small', 'medium'
Enum -
labelCol label 标签布局,通 <Col> 组件,设置 span offset 值,如 {span: 8, offset: 16},该项仅在垂直表单有效 Object -
wrapperCol 需要为输入控件设置布局样式时,使用该属性,用法同 labelCol Object -
help 自定义提示信息,如不设置,则会根据校验规则自动生成. ReactNode -
extra 额外的提示信息,和 help 类似,当需要错误信息和提示文案同时出现时,可以使用这个。 位于错误信息后面 ReactNode -
validateState 校验状态,如不设置,则会根据校验规则自动生成

可选值:
'error'(失败)
'success'(成功)
'loading'(校验中)
'warning'(警告)
Enum -
hasFeedback 配合 validateState 属性使用,是否展示 success/loading 的校验状态图标, 目前只有Input支持 Boolean false
children node 或者 function(values) ReactNode/Function -
fullWidth 单个 Item 中表单类组件宽度是否是100% Boolean -
labelAlign 标签的位置

可选值:
'top'(上)
'left'(左)
'inset'(内)
Enum -
labelTextAlign 标签的左右对齐方式

可选值:
'left'(左)
'right'(右)
Enum -
required [表单校验] 不能为空 Boolean -
asterisk required 的星号是否显示 Boolean -
requiredMessage required 自定义错误信息 String -
requiredTrigger required 自定义触发方式 String/Array -
min [表单校验] 最小值 Number -
max [表单校验] 最大值 Number -
minmaxMessage min/max 自定义错误信息 String -
minmaxTrigger min/max 自定义触发方式 String/Array -
minLength [表单校验] 字符串最小长度 / 数组最小个数 Number -
maxLength [表单校验] 字符串最大长度 / 数组最大个数 Number -
minmaxLengthMessage minLength/maxLength 自定义错误信息 String -
minmaxLengthTrigger minLength/maxLength 自定义触发方式 String/Array -
length [表单校验] 字符串精确长度 / 数组精确个数 Number -
lengthMessage length 自定义错误信息 String -
lengthTrigger length 自定义触发方式 String/Array -
pattern 正则校验 any -
patternMessage pattern 自定义错误信息 String -
patternTrigger pattern 自定义触发方式 String/Array -
format [表单校验] 四种常用的 pattern

可选值:
'number', 'email', 'url', 'tel'
Enum -
formatMessage format 自定义错误信息 String -
formatTrigger format 自定义触发方式 String/Array -
validator [表单校验] 自定义校验函数

签名:
Function() => void
Function -
validatorTrigger validator 自定义触发方式 String/Array -
autoValidate 是否修改数据时自动触发校验 Boolean -
device 预设屏幕宽度

可选值:
'phone', 'tablet', 'desktop'
Enum -
colSpan 在响应式布局模式下,表单项占多少列 Number -
labelWidth 在响应式布局下,且label在左边时,label的宽度是多少 String/Number 100
isPreview 是否开启预览态 Boolean -
renderPreview 预览态模式下渲染的内容

签名:
Function(value: any) => void
参数:
value: {any} 根据包裹的组件的 value 类型而决定
Function -

Form.Submit#

继承 Button API

参数 说明 类型 默认值
onClick 点击提交后触发

签名:
Function(value: Object, errors: Object, field: class) => void
参数:
value: {Object} 数据
errors: {Object} 错误数据
field: {class} 实例
Function func.noop
validate 是否校验/需要校验的 name 数组 Boolean/Array -
field 自定义 field (在 Form 内不需要设置) Object -

Form.Reset#

继承 Button API

参数 说明 类型 默认值
names 自定义重置的字段 Array -
onClick 点击提交后触发

签名:
Function() => void
Function func.noop
toDefault 返回默认值 Boolean -
field 自定义 field (在 Form 内不需要设置) Object -

Form.Error#

自定义错误展示

参数 说明 类型 默认值
name 表单名 String/Array -
field 自定义 field (在 Form 内不需要设置) Object -
children 自定义错误渲染, 可以是 node 或者 function(errors, state) ReactNode/Function -

关于校验#

  • 建议一个FormItem放一个组件, 方便错误提示跟随组件展示
  • 组件必须是FormItem的第一层子元素
  • 详细校验请查看 Field 组件文档的 rules

复杂表单场景#

如果您的表单场景非常复杂,比如动态渲染,大量字段,复杂数据结构,复杂联动校验,可以考虑使用 uform,uform已经封装了所有fusion组件,保证您开箱即用