表单布局、校验、数据提交操作时用到。 组件的设计思想可以看这篇文章 https://zhuanlan.zhihu.com/p/56280821
nodeName
作为 name、idsize=medium
, 并且会控制 FormItem 内所有组件的size。 如果想修改组件的size <FormItem size="small" >
<p>
标签)或者组件向上偏离,可以通过 className="next-form-text-align"
辅助调整<FormItem>
直接包裹的组件才能展示校验错误提示。如果界面不展示错误信息,请检查是否有多个层级。 比如 <FormItem><div><Input/></div></FormItem>
是无法展示校验信息的。<Form field={false}>
来关闭数据获取,变成一个纯布局组件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"
做调整
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);
验证码获取
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);
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
文字左右对齐方式
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
文字左右对齐方式
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组件,其他组件不适用)
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 嵌套
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上设置布局)
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+
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" 的元素
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
wrapperCol
的 Grid.Col
响应式属性实现响应式
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 />
有效。
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);
基本的表单校验例子。
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);
基本的表单校验例子。
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
可以实现较复杂功能
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);
展示和表单相关的其他组件。
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 使用
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=""
然后自己放置展示错误的地方
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
属性,并通过视觉设计上的高亮提示用户。
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
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切换表单元素的预览态,切换前后布局结构相同
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
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 | - |
手动传递了 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 | - |
继承 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 | - |
继承 Button API
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
names | 自定义重置的字段 | Array | - |
onClick | 点击提交后触发 签名: Function() => void |
Function | func.noop |
toDefault | 返回默认值 | Boolean | - |
field | 自定义 field (在 Form 内不需要设置) | Object | - |
自定义错误展示
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
name | 表单名 | String/Array | - |
field | 自定义 field (在 Form 内不需要设置) | Object | - |
children | 自定义错误渲染, 可以是 node 或者 function(errors, state) | ReactNode/Function | - |
Field
组件文档的 rules如果您的表单场景非常复杂,比如动态渲染,大量字段,复杂数据结构,复杂联动校验,可以考虑使用 uform,uform已经封装了所有fusion组件,保证您开箱即用