Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Form 组件:支持全局配置校验错误信息,支持组件统一配置校验错误信息 #359

Merged
151 changes: 99 additions & 52 deletions examples/config-provider/config-provider.md

Large diffs are not rendered by default.

140 changes: 124 additions & 16 deletions examples/form/demos/validate-message.vue
Original file line number Diff line number Diff line change
@@ -1,58 +1,157 @@
<template>
<div>
<t-form :data="formData" ref="form" @reset="onReset" @submit="onSubmit" :colon="true">
<t-form-item label="姓名" name="name">
<t-input v-model="formData.name" placeholder="请输入内容"></t-input>
<!-- 可以使用全局 ConfigProvider errorMessage 配置规则校验结果描述,而无需给每一个表单都配置校验信息 -->
<div>
<t-radio-group v-model="errorConfig" variant="default-filled">
<t-radio-button value="default">
<t-popup content="Form.errorMessage 为空,使用组件内置校验信息。重置后,点击提交观察校验结果信息">
使用表单默认校验信息
</t-popup>
</t-radio-button>
<t-radio-button value="config">
<t-popup content="统一配置 Form.errorMessage,使用自定义配置的校验信息。重置后,点击提交观察校验结果信息">
表单统一配置校验信息
</t-popup>
</t-radio-button>
</t-radio-group>
</div>
<br /><br />
<!-- error-message 非必需 -->
<t-form
:data="formData"
:rules="rules"
:error-message="errorConfig === 'default' ? undefined : errorMessage"
ref="form"
@reset="onReset"
@submit="onSubmit"
scrollToFirstError="smooth"
>
<t-form-item label="用户名" help="这是用户名字段帮助说明" name="account">
<t-input v-model="formData.account"></t-input>
</t-form-item>
<t-form-item label="手机号码" name="tel">
<t-input v-model="formData.tel" placeholder="请输入内容"></t-input>
<t-form-item label="个人简介" help="一句话介绍自己" name="description">
<t-input v-model="formData.description"></t-input>
</t-form-item>
<t-form-item label="接收短信" name="status">
<t-switch v-model="formData.status"></t-switch>
<t-form-item label="密码" name="password">
<t-input type="password" v-model="formData.password"></t-input>
</t-form-item>
<t-form-item label="邮箱" name="email">
<t-input v-model="formData.email"></t-input>
</t-form-item>
<t-form-item label="性别" name="gender">
<t-radio-group v-model="formData.gender">
<t-radio value="1">男</t-radio>
<t-radio value="2">女</t-radio>
<t-radio value="male">男</t-radio>
<t-radio value="femal">女</t-radio>
</t-radio-group>
</t-form-item>
<t-form-item label="课程" name="course">
<t-checkbox-group v-model="formData.course" :options="courseOptions"></t-checkbox-group>
</t-form-item>
<t-form-item label="学院" name="college">
<t-select v-model="formData.college" class="demo-select-base" clearable>
<t-option v-for="(item, index) in options" :value="item.value" :label="item.label" :key="index">
{{ item.label }}
</t-option>
</t-select>
</t-form-item>
<t-form-item
label="入学时间"
name="date"
:rules="[{ date: { delimiters: ['/', '-', '.'] }, message: '日期格式有误' }]"
>
<t-input v-model="formData.date"></t-input>
</t-form-item>
<t-form-item label="个人网站" name="content.url">
<t-input v-model="formData.content.url"></t-input>
</t-form-item>
<t-form-item style="padding-top: 8px">
<t-button theme="primary" type="submit" style="margin-right: 10px">提交</t-button>
<t-button theme="default" variant="base" type="reset">重置</t-button>
<t-button theme="default" variant="base" type="reset" style="margin-right: 10px">重置</t-button>
<t-button theme="default" variant="base" @click="handleClear">清空校验结果</t-button>
</t-form-item>
</t-form>
</div>
</template>
<script>
/* eslint-disable no-template-curly-in-string */
const INITIAL_DATA = {
name: '',
tel: '',
account: '',
password: '',
description: '',
email: '',
gender: '',
college: '',
date: '',
content: {
url: '',
},
course: [],
status: false,
};

export default {
data() {
return {
errorConfig: 'default',
formData: { ...INITIAL_DATA },
courseOptions: [
{ label: '语文', value: '1' },
{ label: '数学', value: '2' },
{ label: '英语', value: '3' },
{ label: '体育', value: '4' },
],
options: [
{ label: '计算机学院', value: '1' },
{ label: '软件学院', value: '2' },
{ label: '物联网学院', value: '3' },
],
errorMessage: {
date: '${name}不正确',
url: '${name}不正确',
required: '请输入${name}',
max: '${name}字符长度不能超过 ${validate} 个字符,一个中文等于两个字符',
min: '${name}字符长度不能少于 ${validate} 个字符,一个中文等于两个字符',
len: '${name}字符长度必须是 ${validate}',
pattern: '${name}不正确',
validator: '${name}有误',
},
rules: {
account: [
{ required: true },
// { enum: ['sheep', 'name'] },
{ min: 2 },
{ max: 10, type: 'warning' },
],
description: [
{ validator: (val) => val.length >= 5 },
{ validator: (val) => val.length < 10, message: '不能超过 20 个字,中文长度等于英文长度' },
],
password: [
{ required: true },
{ len: 8, message: '请输入 8 位密码' },
{ pattern: /[A-Z]+/, message: '密码必须包含大写字母' },
],
email: [{ required: true }, { email: { ignore_max_length: true } }],
gender: [{ required: true }],
course: [
{ required: true },
{ validator: (val) => val.length <= 2, message: '最多选择 2 门课程', type: 'warning' },
],
'content.url': [
{ required: true },
{
url: {
protocols: ['http', 'https', 'ftp'],
require_protocol: true,
},
},
],
},
};
},

methods: {
// 重置方法:this.$refs.reset()
onReset() {
this.$message.success('重置成功');
},
// 提交方法:this.$refs.submit()
onSubmit({ validateResult, firstError }) {
if (validateResult === true) {
this.$message.success('提交成功');
Expand All @@ -61,6 +160,15 @@ export default {
this.$message.warning(firstError);
}
},
handleClear() {
this.$refs.form.clearValidate();
},
},
};
</script>

<style scoped>
.demo-select-base {
width: 300px;
}
</style>
32 changes: 25 additions & 7 deletions examples/form/form.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
colon | Boolean | false | 是否在表单标签字段右侧显示冒号 | N
data | Object | {} | 表单数据。TS 类型:`FormData` | N
disabled | Boolean | undefined | 是否禁用整个表单 | N
errorMessage | Object | - | 表单错误信息配置,示例:`{ idcard: '请输入正确的身份证号码', max: '字符长度不能超过 ${max}' }`。TS 类型:`FormErrorMessage`。[详细类型定义](https://github.com/Tencent/tdesign-vue/tree/develop/src/form/type.ts) | N
formControlledComponents | Array | - | 允许表单统一控制禁用状态的组件名称列表,可以是自定义组件,默认有:TInput、TInputNumber、TCascader、TSelect、TOption、TSwitch、TCheckbox、TCheckboxGroup、TRadio、TRadioGroup、TTreeSelect、TDatePicker、TTimePicker、TUpload、TTransfer、TSlider。如果是自定义组件,组件内部需要包含可以控制表单禁用状态的变量 `formDisabled`。TS 类型:`Array<string>` | N
errorMessage | Object | - | 表单错误信息配置,示例:`{ idcard: '请输入正确的身份证号码', max: '字符长度不能超过 ${max}' }`。TS 类型:`FormErrorMessage` | N
formControlledComponents | Array | - | 允许表单统一控制禁用状态的自定义组件名称列表。默认会有组件库的全部输入类组件:TInput、TInputNumber、TCascader、TSelect、TOption、TSwitch、TCheckbox、TCheckboxGroup、TRadio、TRadioGroup、TTreeSelect、TDatePicker、TTimePicker、TUpload、TTransfer、TSlider。对于自定义组件,组件内部需要包含可以控制表单禁用状态的变量 `formDisabled`。示例:`['CustomUpload', 'CustomInput']`。TS 类型:`Array<string>` | N
labelAlign | String | right | 表单字段标签对齐方式:左对齐、右对齐、顶部对齐。可选项:left/right/top | N
labelWidth | String / Number | '100px' | 可以整体设置label标签宽度,默认为100px | N
layout | String | vertical | 表单布局,有两种方式:纵向布局 和 行内布局。可选项:vertical/inline | N
Expand Down Expand Up @@ -40,10 +40,10 @@ validate | `(result: ValidateResultContext<FormData>)` | 校验结束后触发

名称 | 参数 | 返回值 | 描述
-- | -- | -- | --
clearValidate | `(fields?: Array<string>)` | - | 清空校验结果。可使用 fields 指定清除部分字段的校验结果,fields 值为空则表示清除所有字段校验结果。清除邮箱校验结果示例:`clearValidate(['email'])`
reset | - | - | 重置表单,表单里面没有重置按钮`<button type="reset" />`时可以使用该方法
submit | - | - | 提交表单,表单里面没有提交按钮`<button type="submit" />`时可以使用该方法
validate | `(params?: FormValidateParams)` | `FormValidateResult<FormData>` | 校验函数关于参数params.fields 表示校验字段,如果设置了 fields ,本次校验将仅对这些字段进行校验。params.trigger 表示本次触发校验的范围,'blur' 表示只触发校验规则设定为 trigger='blur' 的字段,'change' 表示只触发校验规则设定为 trigger='change' 的字段,默认触发全范围校验。关于返回值返回值为 true 表示校验通过;如果校验不通过,返回值为校验结果列表。[详细类型定义](https://github.com/Tencent/tdesign-vue/tree/develop/src/form/type.ts)。<br/>`interface FormValidateParams { fields?: Array<string>; trigger?: ValidateTriggerType }`<br/><br/>`type ValidateTriggerType = 'blur' | 'change' | 'all'`<br/>
clearValidate | `(fields?: Array<keyof FormData>)` | - | 清空校验结果。可使用 fields 指定清除部分字段的校验结果,fields 值为空则表示清除所有字段校验结果。清除邮箱校验结果示例:`clearValidate(['email'])`
reset | `(params?: FormResetParams)` | - | 重置表单,表单里面没有重置按钮`<button type="reset" />`时可以使用该方法,默认重置全部字段为空,此方法不会触发 `reset` 事件。<br />如果表单属性 `resetType='empty'` 或者 `reset.type='empty'` 会重置为空;<br />如果表单属性 `resetType='initial'` 或者 `reset.type='initial'` 会重置为表单初始值。<br />`reset.fields` 用于设置具体重置哪些字段(重置指定字段的特性处于开发中),示例:`reset({ type: 'initial', fields: ['name', 'age'] })`。[详细类型定义](https://github.com/Tencent/tdesign-vue/tree/develop/src/form/type.ts)。<br/>`interface FormResetParams { type: 'initial' | 'empty'; fields?: Array<keyof FormData> }`<br/>
submit | - | - | 提交表单,表单里面没有提交按钮`<button type="submit" />`时可以使用该方法,此方法不会触发 `submit` 事件
validate | `(params?: FormValidateParams)` | `FormValidateResult<FormData>` | 校验函数,泛型 `FormData` 表示表单数据 TS 类型。【关于参数params.fields 表示校验字段,如果设置了 fields ,本次校验将仅对这些字段进行校验。params.trigger 表示本次触发校验的范围,'blur' 表示只触发校验规则设定为 trigger='blur' 的字段,'change' 表示只触发校验规则设定为 trigger='change' 的字段,默认触发全范围校验。<br />【关于返回值返回值为 true 表示校验通过;如果校验不通过,返回值为校验结果列表。[详细类型定义](https://github.com/Tencent/tdesign-vue/tree/develop/src/form/type.ts)。<br/>`interface FormValidateParams { fields?: Array<string>; trigger?: ValidateTriggerType }`<br/><br/>`type ValidateTriggerType = 'blur' | 'change' | 'all'`<br/>

### FormItem Props

Expand Down Expand Up @@ -80,4 +80,22 @@ telnumber | Boolean | - | 内置校验方法,校验值是否为手机号码,
trigger | String | change | 校验触发方式。可选项:change/blur | N
type | String | error | 校验未通过时呈现的错误信息类型,有 告警信息提示 和 错误信息提示 等两种。可选项:error/warning | N
url | Boolean / Object | - | 内置校验方法,校验值是否为网络链接地址,[参数文档](https://github.com/validatorjs/validator.js),示例:`{ url: { protocols: ['http','https','ftp'] }, message: '请输入正确的 Url 地址' }`。TS 类型:`boolean | IsURLOptions`。[详细类型定义](https://github.com/Tencent/tdesign-vue/tree/develop/src/form/type.ts) | N
validator | Function | - | 自定义校验规则。TS 类型:`CustomValidator`。[详细类型定义](https://github.com/Tencent/tdesign-vue/tree/develop/src/form/type.ts) | N
validator | Function | - | 自定义校验规则,示例:`{ validator: (val) => val.length > 0, message: '请输入内容'}`。TS 类型:`CustomValidator`。[详细类型定义](https://github.com/Tencent/tdesign-vue/tree/develop/src/form/type.ts) | N

### FormErrorMessage

名称 | 类型 | 默认值 | 说明 | 必传
-- | -- | -- | -- | --
boolean | String | - | 布尔类型校验不通过时的表单项显示文案,全局配置默认是:`'${name}数据类型必须是布尔类型'` | N
date | String | - | 日期校验规则不通过时的表单项显示文案,全局配置默认是:`'请输入正确的${name}'` | N
enum | String | - | 枚举值校验规则不通过时的表单项显示文案,全局配置默认是:`${name}只能是${validate}等` | N
idcard | String | - | 身份证号码校验不通过时的表单项显示文案,全局配置默认是:`'请输入正确的${name}'` | N
len | String | - | 值长度校验不通过时的表单项显示文案,全局配置默认是:`'${name}字符长度必须是 ${validate}'` | N
max | String | - | 值的长度太长或值本身太大时,校验不通过的表单项显示文案,全局配置默认是:`'${name}字符长度不能超过 ${validate} 个字符,一个中文等于两个字符'` | N
min | String | - | 值的长度太短或值本身太小时,校验不通过的表单项显示文案,全局配置默认是:`'${name}字符长度不能少于 ${validate} 个字符,一个中文等于两个字符'` | N
number | String | - | 数字类型校验不通过时的表单项显示文案,全局配置默认是:`'${name}必须是数字'` | N
pattern | String | - | 正则表达式校验不通过时的表单项显示文案,全局配置默认是:`'请输入正确的${name}'` | N
required | String | - | 没有填写必填项时的表单项显示文案,全局配置默认是:`'${name}必填'` | N
telnumber | String | - | 手机号号码校验不通过时的表单项显示文案,全局配置默认是:`'请输入正确的${name}'` | N
url | String | - | 链接校验规则不通过时的表单项显示文案,全局配置默认是:`'请输入正确的${name}'` | N
validator | String | - | 自定义校验规则校验不通过时的表单项显示文案,全局配置默认是:'${name}不符合要求' | N
16 changes: 16 additions & 0 deletions src/config-provider/en_US_config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-template-curly-in-string */
import { GlobalConfigProvider } from './type';

// 文件有效,为国际化做准备
Expand Down Expand Up @@ -121,6 +122,21 @@ const GLOBAL_CONFIG_EN: GlobalConfigProvider = {
},
form: {
requiredMark: true,
errorMessage: {
date: '${name} is invalid',
url: '${name} is invalid',
required: '${name} is required',
max: '${name} must be at least ${validate} characters',
min: '${name} cannot be longer than ${validate} characters',
len: '${name} must be exactly ${validate} characters',
enum: '${name} must be one of ${validate}',
idcard: '${name} is invalid',
telnumber: '${name} is invalid',
pattern: '${name} is invalid',
validator: '${name} is invalid',
boolean: '${name} is not a boolean',
number: '${name} must be a number',
},
},
input: {
placeholder: '',
Expand Down
Loading