由輸入框、選擇器、單選框、多選框等控件組成,用以收集、校驗(yàn)、提交數(shù)據(jù)
包括各種表單項(xiàng),比如輸入框、選擇器、開關(guān)、單選框、多選框等。
在 Form 組件中,每一個(gè)表單域由一個(gè) Form-Item 組件構(gòu)成,表單域中可以放置各種類型的表單控件,包括 Input、Select、Checkbox、Radio、Switch、DatePicker、TimePicker
constructor(props) {
super(props);
this.state = {
form: {
name: '',
region: '',
date1: null,
date2: null,
delivery: false,
type: [],
resource: '',
desc: ''
}
};
}
onSubmit(e) {
e.preventDefault();
}
onChange(key, value) {
this.state.form[key] = value;
this.forceUpdate();
}
render() {
return (
<Form model={this.state.form} labelWidth="80" onSubmit={this.onSubmit.bind(this)}>
<Form.Item label="活動(dòng)名稱">
<Input value={this.state.form.name} onChange={this.onChange.bind(this, 'name')}></Input>
</Form.Item>
<Form.Item label="活動(dòng)區(qū)域">
<Select value={this.state.form.region} placeholder="請選擇活動(dòng)區(qū)域">
<Select.Option label="區(qū)域一" value="shanghai"></Select.Option>
<Select.Option label="區(qū)域二" value="beijing"></Select.Option>
</Select>
</Form.Item>
<Form.Item label="活動(dòng)時(shí)間">
<Layout.Col span="11">
<Form.Item prop="date1" labelWidth="0px">
<DatePicker
value={this.state.form.date1}
placeholder="選擇日期"
onChange={this.onChange.bind(this, 'date1')}
/>
</Form.Item>
</Layout.Col>
<Layout.Col className="line" span="2">-</Layout.Col>
<Layout.Col span="11">
<Form.Item prop="date2" labelWidth="0px">
<TimePicker
value={this.state.form.date2}
selectableRange="18:30:00 - 20:30:00"
placeholder="選擇時(shí)間"
onChange={this.onChange.bind(this, 'date2')}
/>
</Form.Item>
</Layout.Col>
</Form.Item>
<Form.Item label="即時(shí)配送">
<Switch
onText=""
offText=""
value={this.state.form.delivery}
onChange={this.onChange.bind(this, 'delivery')}
/>
</Form.Item>
<Form.Item label="活動(dòng)性質(zhì)">
<Checkbox.Group value={this.state.form.type} onChange={this.onChange.bind(this, 'type')}>
<Checkbox label="美食/餐廳線上活動(dòng)" name="type"></Checkbox>
<Checkbox label="地推活動(dòng)" name="type"></Checkbox>
<Checkbox label="線下主題活動(dòng)" name="type"></Checkbox>
<Checkbox label="單純品牌曝光" name="type"></Checkbox>
</Checkbox.Group>
</Form.Item>
<Form.Item label="特殊資源">
<Radio.Group value={this.state.form.resource}>
<Radio value="線上品牌商贊助"></Radio>
<Radio value="線下場地免費(fèi)"></Radio>
</Radio.Group>
</Form.Item>
<Form.Item label="活動(dòng)形式">
<Input type="textarea" value={this.state.form.desc} onChange={this.onChange.bind(this, 'desc')}></Input>
</Form.Item>
<Form.Item>
<Button type="primary" nativeType="submit">立即創(chuàng)建</Button>
<Button>取消</Button>
</Form.Item>
</Form>
)
}
當(dāng)垂直方向空間受限且表單較簡單時(shí),可以在一行內(nèi)放置表單。
Form 組件的 type
屬性可以控制表單的類型,當(dāng)設(shè)為 inline
時(shí)可以讓表單域變?yōu)樾袃?nèi)的表單域
constructor(props) {
super(props);
this.state = {
form: {
user: '',
region: ''
}
};
}
onSubmit(e) {
e.preventDefault();
console.log('submit!');
}
onChange(key, value) {
this.setState({
form: Object.assign(this.state.form, { [key]: value })
});
}
render() {
return (
<Form inline={true} model={this.state.form} onSubmit={this.onSubmit.bind(this)} className="demo-form-inline">
<Form.Item>
<Input value={this.state.form.user} placeholder="審批人" onChange={this.onChange.bind(this, 'user')}></Input>
</Form.Item>
<Form.Item>
<Select value={this.state.form.region} placeholder="活動(dòng)區(qū)域">
<Select.Option label="區(qū)域一" value="shanghai"></Select.Option>
<Select.Option label="區(qū)域二" value="beijing"></Select.Option>
</Select>
</Form.Item>
<Form.Item>
<Button nativeType="submit" type="primary">查詢</Button>
</Form.Item>
</Form>
)
}
根據(jù)具體目標(biāo)和制約因素,選擇最佳的標(biāo)簽對齊方式。
通過設(shè)置 labelPosition
屬性可以改變表單域標(biāo)簽的位置,可選值為 top
、left
,當(dāng)設(shè)為 top
時(shí)標(biāo)簽會(huì)置于表單域的頂部
constructor(props) {
super(props);
this.state = {
labelPosition: 'right',
form: {
name: '',
region: '',
type: ''
}
};
}
onPositionChange(value) {
this.setState({ labelPosition: value });
}
onChange(key, value) {
this.setState({
form: Object.assign(this.state.form, { [key]: value })
});
}
render() {
return (
<div>
<Radio.Group size="small" value={this.state.labelPosition} onChange={this.onPositionChange.bind(this)}>
<Radio.Button value="left">左對齊</Radio.Button>
<Radio.Button value="right">右對齊</Radio.Button>
<Radio.Button value="top">頂部對齊</Radio.Button>
</Radio.Group>
<div style={{ margin: 20 }}></div>
<Form labelPosition={this.state.labelPosition} labelWidth="100" model={this.state.form} className="demo-form-stacked">
<Form.Item label="名稱">
<Input value={this.state.form.name} onChange={this.onChange.bind(this, 'name')}></Input>
</Form.Item>
<Form.Item label="活動(dòng)區(qū)域">
<Input value={this.state.form.region} onChange={this.onChange.bind(this, 'region')}></Input>
</Form.Item>
<Form.Item label="活動(dòng)展開形式">
<Input value={this.state.form.type} onChange={this.onChange.bind(this, 'type')}></Input>
</Form.Item>
</Form>
</div>
)
}
在防止用戶犯錯(cuò)的前提下,盡可能讓用戶更早地發(fā)現(xiàn)并糾正錯(cuò)誤。
Form 組件提供了表單驗(yàn)證的功能,只需要通過
rule
屬性傳入約定的驗(yàn)證規(guī)則,并 Form-Item 的 prop
屬相設(shè)置為需校驗(yàn)的字段名即可。校驗(yàn)規(guī)則參見 async-validator
constructor(props) {
super(props);
this.state = {
form: {
name: '',
region: '',
date1: null,
date2: null,
delivery: false,
type: [],
resource: '',
desc: ''
},
rules: {
name: [
{ required: true, message: '請輸入活動(dòng)名稱', trigger: 'blur' }
],
region: [
{ required: true, message: '請選擇活動(dòng)區(qū)域', trigger: 'change' }
],
date1: [
{ type: 'date', required: true, message: '請選擇日期', trigger: 'change' }
],
date2: [
{ type: 'date', required: true, message: '請選擇時(shí)間', trigger: 'change' }
],
type: [
{ type: 'array', required: true, message: '請至少選擇一個(gè)活動(dòng)性質(zhì)', trigger: 'change' }
],
resource: [
{ required: true, message: '請選擇活動(dòng)資源', trigger: 'change' }
],
desc: [
{ required: true, message: '請?zhí)顚懟顒?dòng)形式', trigger: 'blur' }
]
}
};
}
handleSubmit(e) {
e.preventDefault();
this.refs.form.validate((valid) => {
if (valid) {
alert('submit!');
} else {
console.log('error submit!!');
return false;
}
});
}
handleReset(e) {
e.preventDefault();
this.refs.form.resetFields();
}
onChange(key, value) {
this.setState({
form: Object.assign({}, this.state.form, { [key]: value })
});
}
render() {
return (
<Form ref="form" model={this.state.form} rules={this.state.rules} labelWidth="80" className="demo-ruleForm">
<Form.Item label="活動(dòng)名稱" prop="name">
<Input value={this.state.form.name} onChange={this.onChange.bind(this, 'name')}></Input>
</Form.Item>
<Form.Item label="活動(dòng)區(qū)域" prop="region">
<Select value={this.state.form.region} placeholder="請選擇活動(dòng)區(qū)域" onChange={this.onChange.bind(this, 'region')}>
<Select.Option label="區(qū)域一" value="shanghai"></Select.Option>
<Select.Option label="區(qū)域二" value="beijing"></Select.Option>
</Select>
</Form.Item>
<Form.Item label="活動(dòng)時(shí)間" required={true}>
<Layout.Col span="11">
<Form.Item prop="date1" labelWidth="0px">
<DatePicker
value={this.state.form.date1}
placeholder="選擇日期"
onChange={this.onChange.bind(this, 'date1')}
/>
</Form.Item>
</Layout.Col>
<Layout.Col className="line" span="2">-</Layout.Col>
<Layout.Col span="11">
<Form.Item prop="date2" labelWidth="0px">
<TimePicker
value={this.state.form.date2}
selectableRange="18:30:00 - 20:30:00"
placeholder="選擇時(shí)間"
onChange={this.onChange.bind(this, 'date2')}
/>
</Form.Item>
</Layout.Col>
</Form.Item>
<Form.Item label="即時(shí)配送" prop="delivery">
<Switch value={this.state.form.delivery} onChange={this.onChange.bind(this, 'delivery')}></Switch>
</Form.Item>
<Form.Item label="活動(dòng)性質(zhì)" prop="type">
<Checkbox.Group value={this.state.form.type} onChange={this.onChange.bind(this, 'type')}>
<Checkbox label="美食/餐廳線上活動(dòng)" name="type"></Checkbox>
<Checkbox label="地推活動(dòng)" name="type"></Checkbox>
<Checkbox label="線下主題活動(dòng)" name="type"></Checkbox>
<Checkbox label="單純品牌曝光" name="type"></Checkbox>
</Checkbox.Group>
</Form.Item>
<Form.Item label="特殊資源" prop="resource">
<Radio.Group value={this.state.form.resource} onChange={this.onChange.bind(this, 'resource')}>
<Radio value="線上品牌商贊助"></Radio>
<Radio value="線下場地免費(fèi)"></Radio>
</Radio.Group>
</Form.Item>
<Form.Item label="活動(dòng)形式" prop="desc">
<Input type="textarea" value={this.state.form.desc} onChange={this.onChange.bind(this, 'desc')}></Input>
</Form.Item>
<Form.Item>
<Button type="primary" onClick={this.handleSubmit.bind(this)}>立即創(chuàng)建</Button>
<Button onClick={this.handleReset.bind(this)}>重置</Button>
</Form.Item>
</Form>
)
}
這個(gè)例子中展示了如何使用自定義驗(yàn)證規(guī)則來完成密碼的二次驗(yàn)證
constructor(props) {
super(props);
this.state = {
form: {
pass: '',
checkPass: '',
age: ''
},
rules: {
pass: [
{ required: true, message: '請輸入密碼', trigger: 'blur' },
{ validator: (rule, value, callback) => {
if (value === '') {
callback(new Error('請輸入密碼'));
} else {
if (this.state.form.checkPass !== '') {
this.refs.form.validateField('checkPass');
}
callback();
}
} }
],
checkPass: [
{ required: true, message: '請?jiān)俅屋斎朊艽a', trigger: 'blur' },
{ validator: (rule, value, callback) => {
if (value === '') {
callback(new Error('請?jiān)俅屋斎朊艽a'));
} else if (value !== this.state.form.pass) {
callback(new Error('兩次輸入密碼不一致!'));
} else {
callback();
}
} }
],
age: [
{ required: true, message: '請?zhí)顚懩挲g', trigger: 'blur' },
{ validator: (rule, value, callback) => {
var age = parseInt(value, 10);
setTimeout(() => {
if (!Number.isInteger(age)) {
callback(new Error('請輸入數(shù)字值'));
} else{
if (age < 18) {
callback(new Error('必須年滿18歲'));
} else {
callback();
}
}
}, 1000);
}, trigger: 'change' }
]
}
};
}
handleSubmit(e) {
e.preventDefault();
this.refs.form.validate((valid) => {
if (valid) {
alert('submit!');
} else {
console.log('error submit!!');
return false;
}
});
}
handleReset(e) {
e.preventDefault();
this.refs.form.resetFields();
}
onChange(key, value) {
this.setState({
form: Object.assign({}, this.state.form, { [key]: value })
});
}
render() {
return (
<Form ref="form" model={this.state.form} rules={this.state.rules} labelWidth="100" className="demo-ruleForm">
<Form.Item label="密碼" prop="pass">
<Input type="password" value={this.state.form.pass} onChange={this.onChange.bind(this, 'pass')} autoComplete="off" />
</Form.Item>
<Form.Item label="確認(rèn)密碼" prop="checkPass">
<Input type="password" value={this.state.form.checkPass} onChange={this.onChange.bind(this, 'checkPass')} autoComplete="off" />
</Form.Item>
<Form.Item label="年齡" prop="age">
<Input value={this.state.form.age} onChange={this.onChange.bind(this, 'age')}></Input>
</Form.Item>
<Form.Item>
<Button type="primary" onClick={this.handleSubmit.bind(this)}>提交</Button>
<Button onClick={this.handleReset.bind(this)}>重置</Button>
</Form.Item>
</Form>
)
}
除了在 Form 組件上一次性傳遞所有的驗(yàn)證規(guī)則外還可以在單個(gè)的表單域上傳遞屬性的驗(yàn)證規(guī)則
constructor(props) {
super(props);
this.state = {
form: {
domains: [{
key: 1,
value: ''
}],
email: ''
},
rules: {
email: [
{ required: true, message: '請輸入郵箱地址', trigger: 'blur' },
{ type: 'email', message: '請輸入正確的郵箱地址', trigger: 'blur,change' }
]
}
};
}
handleSubmit(e) {
e.preventDefault();
this.refs.form.validate((valid) => {
if (valid) {
alert('submit!');
} else {
console.log('error submit!!');
return false;
}
});
}
removeDomain(item, e) {
var index = this.state.form.domains.indexOf(item);
if (index !== -1) {
this.state.form.domains.splice(index, 1);
this.forceUpdate();
}
e.preventDefault();
}
addDomain(e) {
e.preventDefault();
this.state.form.domains.push({
key: this.state.form.domains.length,
value: ''
});
this.forceUpdate();
}
onEmailChange(value) {
this.setState({
form: Object.assign({}, this.state.form, { email: value})
});
}
onDomainChange(index, value) {
this.state.form.domains[index].value = value;
this.forceUpdate();
}
render() {
return (
<Form ref="form" model={this.state.form} rules={this.state.rules} labelWidth="100" className="demo-dynamic">
<Form.Item prop="email" label="郵箱">
<Input value={this.state.form.email} onChange={this.onEmailChange.bind(this)}></Input>
</Form.Item>
{
this.state.form.domains.map((domain, index) => {
return (
<Form.Item
key={index}
label={`域名${index}`}
prop={`domains:${index}`}
rules={{
type: 'object', required: true,
fields: {
value: { required: true, message: '域名不能為空', trigger: 'blur' }
}
}}
>
<Input value={domain.value} onChange={this.onDomainChange.bind(this, index)}></Input>
<Button onClick={this.removeDomain.bind(this, domain)}>刪除</Button>
</Form.Item>
)
})
}
<Form.Item>
<Button type="primary" onClick={this.handleSubmit.bind(this)}>提交</Button>
<Button onClick={this.addDomain.bind(this)}>新增域名</Button>
</Form.Item>
</Form>
)
}
參數(shù) | 說明 | 類型 | 可選值 | 默認(rèn)值 |
---|---|---|---|---|
model | 表單數(shù)據(jù)對象 | object | — | — |
rules | 表單驗(yàn)證規(guī)則 | object | — | — |
inline | 行內(nèi)表單模式 | boolean | — | false |
labelPosition | 表單域標(biāo)簽的位置 | string | right/left/top | right |
labelWidth | 表單域標(biāo)簽的寬度,所有的 form-item 都會(huì)繼承 form 組件的 labelWidth 的值 | string | — | — |
labelSuffix | 表單域標(biāo)簽的后綴 | string | — | — |
方法名 | 說明 |
---|---|
validate(cb) | 對整個(gè)表單進(jìn)行校驗(yàn)的方法 |
validateField(prop, cb) | 對部分表單字段進(jìn)行校驗(yàn)的方法 |
resetFields | 對整個(gè)表單進(jìn)行重置,將所有字段值重置為空并移除校驗(yàn)結(jié)果 |
參數(shù) | 說明 | 類型 | 可選值 | 默認(rèn)值 |
---|---|---|---|---|
prop | 表單域 model 字段 | string | 傳入 Form 組件的 model 中的字段 |
— |
label | 標(biāo)簽文本 | string | — | — |
labelWidth | 表單域標(biāo)簽的的寬度,例如 '50px' | string | — | — |
required | 是否必填,如不設(shè)置,則會(huì)根據(jù)校驗(yàn)規(guī)則自動(dòng)生成 | bolean | — | false |
更多建議: