Form 表单

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

何时使用

需要进行数据收集、数据校验、数据提交功能时。

基础用法

Name
Enter a short name that meets reading habits.
Description
Select
Radio
Switch
Execution day
默认提供水平布局,data参数用于设置表单数据。
<template>
  <d-form :data="formModel">
    <d-form-item field="name" label="Name" help-tips="This is the plan name." extra-info="Enter a short name that meets reading habits.">
      <d-input v-model="formModel.name" />
    </d-form-item>
    <d-form-item field="description" label="Description">
      <d-textarea v-model="formModel.description" />
    </d-form-item>
    <d-form-item field="select" label="Select">
      <d-select v-model="formModel.select" :options="selectOptions" />
    </d-form-item>
    <d-form-item field="radio" label="Radio">
      <d-radio-group direction="row" v-model="formModel.radio">
        <d-radio value="0">Manual execution</d-radio>
        <d-radio value="1">Daily execution</d-radio>
        <d-radio value="2">Weekly execution</d-radio>
      </d-radio-group>
    </d-form-item>
    <d-form-item field="switch" label="Switch">
      <d-switch v-model="formModel.switch"></d-switch>
    </d-form-item>
    <d-form-item field="executionDay">
      <template #label><span>Execution day</span></template>
      <d-checkbox-group v-model="formModel.executionDay" label="Execution day" direction="row">
        <d-checkbox label="Mon" value="Mon" />
        <d-checkbox label="Tue" value="Tue" />
        <d-checkbox label="Wed" value="Wed" />
        <d-checkbox label="Thur" value="Thur" />
        <d-checkbox label="Fri" value="Fri" />
        <d-checkbox label="Sat" value="Sat" />
        <d-checkbox label="Sun" value="Sun" />
      </d-checkbox-group>
    </d-form-item>
    <d-form-operation class="form-demo-form-operation">
      <d-button variant="solid">提交</d-button>
      <d-button>取消</d-button>
    </d-form-operation>
  </d-form>
</template>

<script>
import { defineComponent, reactive, ref, nextTick } from 'vue';

export default defineComponent({
  setup() {
    let formModel = reactive({
      name: '',
      description: '',
      select: 'Options2',
      radio: '0',
      switch: true,
      executionDay: [],
    });
    const selectOptions = reactive(['Options1', 'Options2', 'Options3']);
    return {
      formModel,
      selectOptions,
    };
  },
});
</script>

<style>
.form-demo-form-operation > * {
  margin-right: 8px;
}
</style>

表单样式

大小:
对齐方式:
Name
Description
Execution day
水平排列模式下,label-size可以设置label的宽度,提供smmdlg三种大小,分别对应80px100px150px,默认为mdlabel-align可以设置label的对齐方式,可选值为startcenterend,默认为start
<template>
  <div class="form-btn-groups">
    <div class="form-btn">
      大小:
      <d-radio-group direction="row" v-model="size">
        <d-radio v-for="item in sizeList" :key="item.label" :value="item.value">
          {{ item.label }}
        </d-radio>
      </d-radio-group>
    </div>
    <div class="form-btn">
      对齐方式:
      <d-radio-group direction="row" v-model="align">
        <d-radio v-for="item in alignList" :key="item.label" :value="item.value">
          {{ item.label }}
        </d-radio>
      </d-radio-group>
    </div>
  </div>
  <d-form :data="formModel" :label-size="size" :label-align="align">
    <d-form-item field="name" label="Name">
      <d-input v-model="formModel.name" />
    </d-form-item>
    <d-form-item field="description" label="Description">
      <d-textarea v-model="formModel.description" />
    </d-form-item>
    <d-form-item field="executionDay" label="Execution day">
      <d-checkbox-group v-model="formModel.executionDay" label="Execution day" direction="row">
        <d-checkbox label="Mon" value="Mon" />
        <d-checkbox label="Tue" value="Tue" />
        <d-checkbox label="Wed" value="Wed" />
        <d-checkbox label="Thur" value="Thur" />
        <d-checkbox label="Fri" value="Fri" />
        <d-checkbox label="Sat" value="Sat" />
        <d-checkbox label="Sun" value="Sun" />
      </d-checkbox-group>
    </d-form-item>
    <d-form-operation class="form-demo-form-operation">
      <d-button variant="solid">提交</d-button>
      <d-button>取消</d-button>
    </d-form-operation>
  </d-form>
</template>

<script>
import { defineComponent, reactive, ref } from 'vue';

export default defineComponent({
  setup() {
    const formModel = reactive({
      name: '',
      description: '',
      executionDay: [],
    });
    const size = ref('md');
    const align = ref('start');
    const sizeList = [
      {
        label: 'Small',
        value: 'sm',
      },
      {
        label: 'Middle',
        value: 'md',
      },
      {
        label: 'Large',
        value: 'lg',
      },
    ];
    const alignList = [
      {
        label: 'Start',
        value: 'start',
      },
      {
        label: 'Center',
        value: 'center',
      },
      {
        label: 'End',
        value: 'end',
      },
    ];

    return {
      formModel,
      size,
      sizeList,
      align,
      alignList,
    };
  },
});
</script>

<style>
.form-btn-groups {
  display: flex;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
.form-btn {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  margin-right: 1rem;
}
</style>

垂直排列

Name
Description
Select
Radio
Switch
Execution day
设置layout参数为vertical可启用垂直布局,即label在输入控件的上方。
<template>
  <d-form layout="vertical" :data="formModel">
    <d-form-item field="name" label="Name">
      <d-input v-model="formModel.name" />
    </d-form-item>
    <d-form-item field="description" label="Description">
      <d-textarea v-model="formModel.description" />
    </d-form-item>
    <d-form-item field="select" label="Select">
      <d-select v-model="formModel.select" :options="selectOptions" />
    </d-form-item>
    <d-form-item field="radio" label="Radio">
      <d-radio-group direction="row" v-model="formModel.radio">
        <d-radio value="0">Manual execution</d-radio>
        <d-radio value="1">Daily execution</d-radio>
        <d-radio value="2">Weekly execution</d-radio>
      </d-radio-group>
    </d-form-item>
    <d-form-item field="switch" label="Switch">
      <d-switch v-model="formModel.switch"></d-switch>
    </d-form-item>
    <d-form-item field="executionDay" label="Execution day">
      <d-checkbox-group v-model="formModel.executionDay" label="Execution day" direction="row">
        <d-checkbox label="Mon" value="Mon" />
        <d-checkbox label="Tue" value="Tue" />
        <d-checkbox label="Wed" value="Wed" />
        <d-checkbox label="Thur" value="Thur" />
        <d-checkbox label="Fri" value="Fri" />
        <d-checkbox label="Sat" value="Sat" />
        <d-checkbox label="Sun" value="Sun" />
      </d-checkbox-group>
    </d-form-item>
    <d-form-operation class="form-demo-form-operation">
      <d-button variant="solid">提交</d-button>
      <d-button>取消</d-button>
    </d-form-operation>
  </d-form>
</template>

<script>
import { defineComponent, reactive } from 'vue';

export default defineComponent({
  setup() {
    let formModel = reactive({
      name: '',
      description: '',
      select: 'Options2',
      radio: '0',
      switch: true,
      executionDay: [],
    });
    const selectOptions = reactive(['Options1', 'Options2', 'Options3']);

    return {
      formModel,
      selectOptions,
    };
  },
});
</script>

多列表单

Name
Select
Multiple Select
Execution day
Radio
Switch
搭配Grid栅格布局方案,即可方便的实现多列表单布局效果。
<template>
  <d-form layout="vertical" :data="formModel">
    <d-row :gutter="16">
      <d-col :span="7">
        <d-form-item field="name" label="Name" help-tips="This is the plan name.">
          <d-input v-model="formModel.name" />
        </d-form-item>
      </d-col>
      <d-col :span="7">
        <d-form-item field="select" label="Select">
          <d-select v-model="formModel.select" :options="selectOptions" />
        </d-form-item>
      </d-col>
      <d-col :span="7">
        <d-form-item field="multiSelect" label="Multiple Select">
          <d-select v-model="formModel.multiSelect" :options="selectOptions" multiple />
        </d-form-item>
      </d-col>
    </d-row>
    <d-row :gutter="16">
      <d-col :span="7">
        <d-form-item field="executionDay" label="Execution day">
          <d-checkbox-group v-model="formModel.executionDay" label="Execution day">
            <d-checkbox label="Mon" value="Mon" />
            <d-checkbox label="Tue" value="Tue" />
            <d-checkbox label="Wed" value="Wed" />
            <d-checkbox label="Thur" value="Thur" />
            <d-checkbox label="Fri" value="Fri" />
            <d-checkbox label="Sat" value="Sat" />
            <d-checkbox label="Sun" value="Sun" />
          </d-checkbox-group>
        </d-form-item>
      </d-col>
      <d-col :span="7">
        <d-form-item field="radio" label="Radio">
          <d-radio-group direction="row" v-model="formModel.radio">
            <d-radio value="0">Manual execution</d-radio>
            <d-radio value="1">Daily execution</d-radio>
            <d-radio value="2">Weekly execution</d-radio>
          </d-radio-group>
        </d-form-item>
      </d-col>
      <d-col :span="7">
        <d-form-item field="switch" label="Switch">
          <d-switch v-model="formModel.switch"></d-switch>
        </d-form-item>
      </d-col>
    </d-row>
    <d-form-operation class="form-demo-form-operation">
      <d-button variant="solid">提交</d-button>
      <d-button>取消</d-button>
    </d-form-operation>
  </d-form>
</template>

<script>
import { defineComponent, reactive, ref } from 'vue';

export default defineComponent({
  setup() {
    const formModel = reactive({
      name: '',
      select: 'Options2',
      multiSelect: ref([]),
      executionDay: [],
      radio: '0',
      switch: true,
    });
    const selectOptions = reactive(['Options1', 'Options2', 'Options3']);

    return { formModel, selectOptions };
  },
});
</script>

尺寸控制

尺寸:
Name
Search
InputNumber
Description
Select
AutoComplete
Radio
Switch
Execution day
Date Picker Pro
Time Select
Time Picker
通过size属性可控制所有控件的尺寸。
<template>
  <div class="form-demo-set-form-size">
    尺寸:
    <d-radio-group direction="row" v-model="formSize">
      <d-radio :value="item.value" v-for="item in sizeTypeList" :key="item.value">
        {{ item.label }}
      </d-radio>
    </d-radio-group>
  </div>

  <d-form :data="formModel" :size="formSize">
    <d-form-item field="name" label="Name">
      <d-input v-model="formModel.name" placeholder="请输入" />
    </d-form-item>

    <d-form-item field="search" label="Search">
      <d-search v-model="formModel.search" placeholder="请输入"></d-search>
    </d-form-item>

    <d-form-item field="inputNumber" label="InputNumber">
      <d-input-number v-model="formModel.inputNumber" placeholder="请输入"></d-input-number>
    </d-form-item>

    <d-form-item field="description" label="Description">
      <d-textarea v-model="formModel.description" />
    </d-form-item>

    <d-form-item field="select" label="Select">
      <d-select v-model="formModel.select" :options="selectOptions" />
    </d-form-item>

    <d-form-item field="autoComplete" label="AutoComplete">
      <d-auto-complete :source="source" v-model="formModel.autoComplete"></d-auto-complete>
    </d-form-item>

    <d-form-item field="radio" label="Radio">
      <d-radio-group direction="row" v-model="formModel.radio">
        <d-radio value="0">Manual execution</d-radio>
        <d-radio value="1">Daily execution</d-radio>
        <d-radio value="2">Weekly execution</d-radio>
      </d-radio-group>
    </d-form-item>

    <d-form-item field="switch" label="Switch">
      <d-switch v-model="formModel.switch"></d-switch>
    </d-form-item>

    <d-form-item field="executionDay" label="Execution day">
      <d-checkbox-group v-model="formModel.executionDay" label="Execution day" direction="row">
        <d-checkbox label="Mon" value="Mon" />
        <d-checkbox label="Tue" value="Tue" />
        <d-checkbox label="Wed" value="Wed" />
        <d-checkbox label="Thur" value="Thur" />
        <d-checkbox label="Fri" value="Fri" />
        <d-checkbox label="Sat" value="Sat" />
        <d-checkbox label="Sun" value="Sun" />
      </d-checkbox-group>
    </d-form-item>

    <d-form-item field="datePickerPro" label="Date Picker Pro">
      <d-date-picker-pro v-model="formModel.datePickerPro"></d-date-picker-pro>
    </d-form-item>

    <d-form-item field="timeSelect" label="Time Select">
      <d-time-select v-model="formModel.timeSelect" />
    </d-form-item>

    <d-form-item field="timePicker" label="Time Picker">
      <d-time-picker v-model="formModel.timePicker" placeholder="请选择时间" />
    </d-form-item>

    <d-form-operation class="form-demo-form-operation">
      <d-button variant="solid">提交</d-button>
      <d-button>取消</d-button>
    </d-form-operation>
  </d-form>
</template>

<script>
import { defineComponent, reactive, ref } from 'vue';

export default defineComponent({
  setup() {
    const sizeTypeList = [
      {
        label: 'Small',
        value: 'sm',
      },
      {
        label: 'Middle',
        value: 'md',
      },
      {
        label: 'Large',
        value: 'lg',
      },
    ];
    const formSize = ref('md');

    let formModel = reactive({
      name: '',
      search: '',
      inputNumber: 1,
      description: '',
      select: '',
      autoComplete: '',
      radio: '0',
      switch: true,
      executionDay: [],
      datePickerPro: '',
      timeSelect: '',
      timePicker: '',
    });

    const selectOptions = reactive(['Options1', 'Options2', 'Options3']);
    const source = ref(['C#', 'C', 'C++']);

    return {
      sizeTypeList,
      formSize,
      formModel,
      source,
      selectOptions,
    };
  },
});
</script>

<style>
.form-demo-set-form-size {
  display: flex;
  align-items: center;
  margin-bottom: 16px;
}

.form-demo-form-operation > * {
  margin-right: 8px;
}
</style>

表单校验

用户名
用户信息
年龄
Select
AutoComplete
Radio
Execution day
Date Picker Pro
Range Date Picker Pro
-
<template>
  <d-form ref="formRef" layout="vertical" :data="formData" :rules="rules" :pop-position="['right']">
    <d-form-item
      field="username"
      :rules="[{ required: true, message: '用户名不能为空', trigger: 'blur' }]"
      :show-feedback="false"
      label="用户名"
    >
      <d-input v-model="formData.username" />
    </d-form-item>
    <d-form-item field="userInfo" label="用户信息">
      <d-textarea v-model="formData.userInfo"></d-textarea>
    </d-form-item>
    <d-form-item field="age" label="年龄">
      <d-input v-model="formData.age" />
    </d-form-item>
    <d-form-item field="select" label="Select">
      <d-select v-model="formData.select" :options="selectOptions" allow-clear />
    </d-form-item>
    <d-form-item field="autoComplete" label="AutoComplete">
      <d-auto-complete :source="source" v-model="formData.autoComplete"></d-auto-complete>
    </d-form-item>
    <d-form-item field="radio" label="Radio">
      <d-radio-group direction="row" v-model="formData.radio">
        <d-radio value="0">Manual execution</d-radio>
        <d-radio value="1">Daily execution</d-radio>
        <d-radio value="2">Weekly execution</d-radio>
      </d-radio-group>
    </d-form-item>
    <d-form-item field="executionDay" label="Execution day">
      <d-checkbox-group v-model="formData.executionDay" label="Execution day" direction="row">
        <d-checkbox label="Mon" value="Mon" />
        <d-checkbox label="Tue" value="Tue" />
        <d-checkbox label="Wed" value="Wed" />
        <d-checkbox label="Thur" value="Thur" />
        <d-checkbox label="Fri" value="Fri" />
        <d-checkbox label="Sat" value="Sat" />
        <d-checkbox label="Sun" value="Sun" />
      </d-checkbox-group>
    </d-form-item>
    <d-form-item field="datePickerPro" label="Date Picker Pro">
      <d-date-picker-pro v-model="formData.datePickerPro"></d-date-picker-pro>
    </d-form-item>
    <d-form-item field="rangeDatePickerPro" label="Range Date Picker Pro">
      <d-range-date-picker-pro v-model="formData.rangeDatePickerPro"></d-range-date-picker-pro>
    </d-form-item>
    <d-form-operation class="form-operation-wrap">
      <d-button variant="solid" @click="onClick">提交</d-button>
      <d-button @click="onClear">清除校验结果</d-button>
      <d-button @click="onReset">重置</d-button>
    </d-form-operation>
  </d-form>
</template>

<script>
import { defineComponent, reactive, ref, watch } from 'vue';

export default defineComponent({
  setup() {
    const formRef = ref(null);
    const formData = reactive({
      username: '',
      userInfo: '',
      age: '',
      select: 'Options2',
      autoComplete: '',
      executionDay: ['Tue'],
      radio: '',
      datePickerPro: '',
      rangeDatePickerPro: ['', ''],
    });
    const selectOptions = reactive(['Options1', 'Options2', 'Options3']);
    const source = ref(['C#', 'C', 'C++']);
    const checkAge = (rule, value, callback) => {
      if (!value) {
        return callback(new Error('年龄不能为空'));
      }
      setTimeout(() => {
        if (value < 18) {
          return callback(new Error('年龄不能小于18'));
        } else {
          callback();
        }
      }, 1000);
    };

    const checkRangeDatePickerPro = (rule, value, callback) => {
      if (!value || (!value[0] && !value[1])) {
        return callback(new Error('请选择日期范围'));
      } else if (!value[0]) {
        return callback(new Error('请选择开始日期'));
      } else if (!value[1]) {
        return callback(new Error('请选择结束日期'));
      } else {
        return callback();
      }
    };

    const rules = {
      username: [{ min: 3, max: 6, message: '用户名需不小于3个字符,不大于6个字符', trigger: 'change' }],
      userInfo: [{ required: true, message: '用户信息不能为空', trigger: 'blur' }],
      age: [{ validator: checkAge }],
      select: [{ required: true, message: '请选择', trigger: 'change' }],
      autoComplete: [{ required: true, message: '请选择', trigger: 'change' }],
      executionDay: [{ type: 'array', required: true, message: '请至少选择一个执行时间', trigger: 'change' }],
      radio: [{ required: true, message: '请选择', trigger: 'change' }],
      datePickerPro: [{ type: 'object', required: true, message: '请选择日期', trigger: 'change' }],
      rangeDatePickerPro: [
        { validator: checkRangeDatePickerPro },
        { type: 'array', required: true, message: '请选择日期范围', trigger: 'change' },
      ],
    };

    const onClick = () => {
      formRef.value.validate((isValid, invalidFields) => {
        console.log(isValid);
        console.log(invalidFields);
      });
    };

    const onClear = () => {
      formRef.value.clearValidate();
    };

    const onReset = () => {
      formRef.value.resetFields();
    };

    return { formRef, formData, selectOptions, source, rules, onClick, onClear, onReset };
  },
});
</script>

<style>
.form-operation-wrap > * {
  margin-right: 8px;
}
</style>

Form 参数

参数名类型默认值说明跳转 demo
dataobject{}必选,表单数据基础用法
layoutLayout'horizontal'可选,设置表单的排列方式垂直排列
label-sizeLabelSize'md'可选,设置 label 的宽度,默认为 100px,sm 对应 80px,lg 对应 150px表单样式
label-alignLabelAlign'start'可选,设置水平布局方式下,label 对齐方式表单样式
rulesFormRules--可选,设置表单的校验规则表单校验
message-typeMessageType'popover'可选,设置校验信息的提示方式
pop-positionPopPosition['right','bottom']可选,消息显示为 popover 时,popover 弹出方向
validate-on-rule-changebooleanfalse可选,是否在 rules 改变后立即触发一次验证
show-feedbackbooleanfalse可选,是否展示校验结果反馈图标
disabledbooleanfalse可选,是否禁用该表单内的所有组件。
sizeFormSize--可选,用于控制该表单内组件的尺寸
hide-required-markbooleanfalse可选,是否隐藏所有表单项的必选标记
style-typeStyleType'default'可选,设置表单为灰色表单
append-to-body-scroll-strategyAppendToBodyScrollStrategy'reposition'可选,消息显示为 popover 时,滚动时 popover 处理策略,默认策略跟随宿主移动;close为滚动时关闭

Form 事件

事件名回调参数说明
validateFunction(field: string, isValid: boolean, message: string) => void表单项被校验后触发

Form 方法

方法名类型说明跳转 Demo
validate(callback?: FormValidateCallback) => Promise表单校验函数表单校验
validateFields(fields: string[], callback?: FormValidateCallback) => Promise校验指定字段
resetFields(fields: string[]) => void重置表单项的值,并移除校验结果
clearValidate(fields: string[]) => void清除校验结果,参数为需要清除的表单项field,默认清除全部

Form 插槽

插槽名说明
default包裹整个表单内容

FormItem 参数

参数名类型默认值说明跳转 demo
labelstring''可选,表单项的名称基础用法
fieldstring''可选,指定验证表单需验证的字段,验证表单时必选该属性基础用法
requiredbooleanfalse可选,表单选项是否必填
rulesFormRuleItem | FormRuleItem[]--可选,表单项的校验规则表单校验
message-typeMessageType--可选,用法同父组件message-type参数,优先级高于父组件,默认继承父组件的值
pop-positionPopPosition--可选,用法同父组件pop-position参数,优先级高于父组件,默认继承父组件的值
show-feedbackboolean--可选,是否展示校验结果反馈图标,优先级高于父组件,默认继承父组件的值
help-tipsstring |helptips''可选,表单项帮助指引提示内容,空字符串表示不设置提示内容。可传入对象类型的参数来自定义提示内容的样式、展开方向等基础用法
extra-infostring''可选,附件信息,一般用于补充表单选项的说明基础用法
feedback-statusFeedbackStatus--可选,手动指定当前 control 状态反馈

FormItem 方法

方法名类型说明
resetField() => void重置表单项的值,并移除校验结果
clearValidate() => void清除校验结果
validate(trigger: string) => Promise表单校验函数

FormItem 插槽

插槽名说明
default包裹单个表单项的输入控件
label标签位置显示的内容
extraInfo自定义表单项额外信息

Form 类型定义

Layout

type Layout = 'horizontal' | 'vertical';

LabelSize

type LabelSize = 'sm' | 'md' | 'lg';

LabelAlign

type LabelAlign = 'start' | 'center' | 'end';

FormRules

type FormRules = Partial<Record<string, Array<FormRuleItem>>>;

MessageType

type MessageType = 'popover' | 'text' | 'none';

PopPosition

type PopPosition =
  | 'top'
  | 'right'
  | 'bottom'
  | 'left'
  | 'top-start'
  | 'top-end'
  | 'right-start'
  | 'right-end'
  | 'bottom-start'
  | 'bottom-end'
  | 'left-start'
  | 'left-end';

FormSize

type FormSize = 'sm' | 'md' | 'lg';

FormValidateCallback

ValidateFieldsError类型参考async-validator

type FormValidateCallback = (isValid: boolean, invalidFields?: ValidateFieldsError) => void;

StyleType

type StyleType = 'default' | 'gray';

AppendToBodyScrollStrategy

type AppendToBodyScrollStrategy = 'close' | 'reposition';

FormItem 类型定义

FormRuleItem

RuleItem类型参考async-validator

interface FormRuleItem extends RuleItem {
  trigger?: Array<string>;
}

FeedbackStatus

type FeedbackStatus = 'success' | 'error' | 'pending';

HelpTips

interface HelpTips {
  content: string; // 提示内容
  position?: PopPosition[]; // 展开方向
  trigger?: 'hover' | 'click'; // 触发方式
  popType?: string; // 提示类型
}
Contributors