Form 表单

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

    注意:非 template/render 模式下,需使用 。

    W3C 标准中有如下规定When there is only one single-line text input field in a form, the user agent should accept Enter in that field as a request to submit the form.

    即:当一个 form 元素中只有一个输入框时,在该输入框中按下回车应提交该表单。如果希望阻止这一默认行为,可以在 <Form> 标签上添加 @submit.native.prevent

    行内表单

    设置属性 inline,表单元素可以水平排列。

    Form 表单 - 图2

    表单控件

    Form 内,每个表单域由 FormItem 组成,可包含的控件有:Input、Radio、Checkbox、Switch、Select、Slider、DatePicker、TimePicker、Cascader、Transfer、InputNumber、Rate、Upload、AutoComplete、ColorPicker。

    FormItem 设置属性 label-for 可以指定原生的 label 标签的 for 属性,配合设置控件的 element-id 属性,可以点击 label 时聚焦控件。

    1. <template>
    2. <Form :model="formItem" :label-width="80">
    3. <FormItem label="Input">
    4. <Input v-model="formItem.input" placeholder="Enter something..."></Input>
    5. </FormItem>
    6. <FormItem label="Select">
    7. <Select v-model="formItem.select">
    8. <Option value="beijing">New York</Option>
    9. <Option value="shanghai">London</Option>
    10. <Option value="shenzhen">Sydney</Option>
    11. </Select>
    12. </FormItem>
    13. <FormItem label="DatePicker">
    14. <Row>
    15. <Col span="11">
    16. <DatePicker type="date" placeholder="Select date" v-model="formItem.date"></DatePicker>
    17. </Col>
    18. <Col span="2" style="text-align: center">-</Col>
    19. <Col span="11">
    20. <TimePicker type="time" placeholder="Select time" v-model="formItem.time"></TimePicker>
    21. </Col>
    22. </Row>
    23. </FormItem>
    24. <FormItem label="Radio">
    25. <RadioGroup v-model="formItem.radio">
    26. <Radio label="male">Male</Radio>
    27. <Radio label="female">Female</Radio>
    28. </RadioGroup>
    29. </FormItem>
    30. <FormItem label="Checkbox">
    31. <CheckboxGroup v-model="formItem.checkbox">
    32. <Checkbox label="Eat"></Checkbox>
    33. <Checkbox label="Sleep"></Checkbox>
    34. <Checkbox label="Run"></Checkbox>
    35. <Checkbox label="Movie"></Checkbox>
    36. </CheckboxGroup>
    37. </FormItem>
    38. <FormItem label="Switch">
    39. <i-switch v-model="formItem.switch" size="large">
    40. <span slot="open">On</span>
    41. <span slot="close">Off</span>
    42. </i-switch>
    43. </FormItem>
    44. <FormItem label="Slider">
    45. <Slider v-model="formItem.slider" range></Slider>
    46. </FormItem>
    47. <FormItem label="Text">
    48. <Input v-model="formItem.textarea" type="textarea" :autosize="{minRows: 2,maxRows: 5}" placeholder="Enter something..."></Input>
    49. </FormItem>
    50. <FormItem>
    51. <Button type="primary">Submit</Button>
    52. <Button style="margin-left: 8px">Cancel</Button>
    53. </FormItem>
    54. </Form>
    55. </template>
    56. <script>
    57. return {
    58. formItem: {
    59. input: '',
    60. select: '',
    61. radio: 'male',
    62. checkbox: [],
    63. switch: true,
    64. date: '',
    65. time: '',
    66. slider: [20, 50],
    67. textarea: ''
    68. }
    69. }
    70. }
    71. }
    72. </script>

    对齐方式

    设置属性 label-position,可以改变表单域标签的位置,left 为左对齐,right 为右对齐,top 会置于表单域顶部。

    Form 表单 - 图4

    表单验证

    Form 组件基于 async-validator 实现的数据验证,给 Form 设置属性 rules,同时给需要验证的 FormItem 设置属性 prop 指向对应字段即可。

    完整的验证规则请参照开源项目 async-validator。

    验证方法也支持 Promise。

    1. <template>
    2. <Form ref="formValidate" :model="formValidate" :rules="ruleValidate" :label-width="80">
    3. <FormItem label="Name" prop="name">
    4. <Input v-model="formValidate.name" placeholder="Enter your name"></Input>
    5. </FormItem>
    6. <FormItem label="E-mail" prop="mail">
    7. <Input v-model="formValidate.mail" placeholder="Enter your e-mail"></Input>
    8. </FormItem>
    9. <FormItem label="City" prop="city">
    10. <Select v-model="formValidate.city" placeholder="Select your city">
    11. <Option value="beijing">New York</Option>
    12. <Option value="shanghai">London</Option>
    13. <Option value="shenzhen">Sydney</Option>
    14. </Select>
    15. </FormItem>
    16. <FormItem label="Date">
    17. <Row>
    18. <Col span="11">
    19. <FormItem prop="date">
    20. <DatePicker type="date" placeholder="Select date" v-model="formValidate.date"></DatePicker>
    21. </FormItem>
    22. </Col>
    23. <Col span="2" style="text-align: center">-</Col>
    24. <Col span="11">
    25. <FormItem prop="time">
    26. <TimePicker type="time" placeholder="Select time" v-model="formValidate.time"></TimePicker>
    27. </FormItem>
    28. </Col>
    29. </Row>
    30. </FormItem>
    31. <FormItem label="Gender" prop="gender">
    32. <RadioGroup v-model="formValidate.gender">
    33. <Radio label="male">Male</Radio>
    34. <Radio label="female">Female</Radio>
    35. </RadioGroup>
    36. </FormItem>
    37. <FormItem label="Hobby" prop="interest">
    38. <CheckboxGroup v-model="formValidate.interest">
    39. <Checkbox label="Eat"></Checkbox>
    40. <Checkbox label="Sleep"></Checkbox>
    41. <Checkbox label="Run"></Checkbox>
    42. <Checkbox label="Movie"></Checkbox>
    43. </CheckboxGroup>
    44. </FormItem>
    45. <FormItem label="Desc" prop="desc">
    46. <Input v-model="formValidate.desc" type="textarea" :autosize="{minRows: 2,maxRows: 5}" placeholder="Enter something..."></Input>
    47. </FormItem>
    48. <Button type="primary" @click="handleSubmit('formValidate')">Submit</Button>
    49. </FormItem>
    50. </Form>
    51. </template>
    52. <script>
    53. export default {
    54. data () {
    55. return {
    56. formValidate: {
    57. name: '',
    58. mail: '',
    59. city: '',
    60. gender: '',
    61. interest: [],
    62. date: '',
    63. time: '',
    64. desc: ''
    65. },
    66. ruleValidate: {
    67. name: [
    68. { required: true, message: 'The name cannot be empty', trigger: 'blur' }
    69. ],
    70. mail: [
    71. { required: true, message: 'Mailbox cannot be empty', trigger: 'blur' },
    72. { type: 'email', message: 'Incorrect email format', trigger: 'blur' }
    73. ],
    74. city: [
    75. { required: true, message: 'Please select the city', trigger: 'change' }
    76. ],
    77. gender: [
    78. { required: true, message: 'Please select gender', trigger: 'change' }
    79. ],
    80. interest: [
    81. { required: true, type: 'array', min: 1, message: 'Choose at least one hobby', trigger: 'change' },
    82. { type: 'array', max: 2, message: 'Choose two hobbies at best', trigger: 'change' }
    83. ],
    84. date: [
    85. { required: true, type: 'date', message: 'Please select the date', trigger: 'change' }
    86. ],
    87. time: [
    88. { required: true, type: 'string', message: 'Please select time', trigger: 'change' }
    89. ],
    90. desc: [
    91. { required: true, message: 'Please enter a personal introduction', trigger: 'blur' },
    92. { type: 'string', min: 20, message: 'Introduce no less than 20 words', trigger: 'blur' }
    93. ]
    94. }
    95. }
    96. },
    97. methods: {
    98. handleSubmit (name) {
    99. this.$refs[name].validate((valid) => {
    100. if (valid) {
    101. this.$Message.success('Success!');
    102. } else {
    103. this.$Message.error('Fail!');
    104. }
    105. })
    106. },
    107. handleReset (name) {
    108. this.$refs[name].resetFields();
    109. }
    110. }
    111. </script>

    自定义验证

    Form 表单 - 图6

    动态增减表单项

    当需要动态维护 FormItem 时,也可以直接给 FormItem 设置属性 rules 来单独为该域做验证。

    动态设置 FormItem 的 prop 属性时,会依据上层的 Form 组件的 model 来获取,查看示例代码。

    FormItem 还可以独立设置 required、error 等属性,详见 API。

    <template>
        <Form ref="formDynamic" :model="formDynamic" :label-width="80" style="width: 300px">
            <FormItem
                    v-for="(item, index) in formDynamic.items"
                    v-if="item.status"
                    :key="index"
                    :label="'Item ' + item.index"
                    :prop="'items.' + index + '.value'"
                    :rules="{required: true, message: 'Item ' + item.index +' can not be empty', trigger: 'blur'}">
                <Row>
                    <Col span="18">
                        <Input type="text" v-model="item.value" placeholder="Enter something..."></Input>
                    </Col>
                    <Col span="4" offset="1">
                        <Button @click="handleRemove(index)">Delete</Button>
                    </Col>
                </Row>
            </FormItem>
            <FormItem>
                <Row>
                    <Col span="12">
                        <Button type="dashed" long @click="handleAdd" icon="md-add">Add item</Button>
                    </Col>
                </Row>
            </FormItem>
            <FormItem>
                <Button type="primary" @click="handleSubmit('formDynamic')">Submit</Button>
                <Button @click="handleReset('formDynamic')" style="margin-left: 8px">Reset</Button>
            </FormItem>
        </Form>
    </template>
    <script>
        export default {
            data () {
                return {
                    index: 1,
                    formDynamic: {
                        items: [
                            {
                                value: '',
                                index: 1,
                                status: 1
                            }
                        ]
                    }
                }
            },
            methods: {
                handleSubmit (name) {
                    this.$refs[name].validate((valid) => {
                        if (valid) {
                            this.$Message.success('Success!');
                        } else {
                            this.$Message.error('Fail!');
                        }
                    })
                },
                handleReset (name) {
                    this.$refs[name].resetFields();
                },
                handleAdd () {
                    this.index++;
                    this.formDynamic.items.push({
                        value: '',
                        index: this.index,
                        status: 1
                    });
                },
                handleRemove (index) {
                    this.formDynamic.items[index].status = 0;
                }
            }
        }
    </script>