From dc0a29be1720b9a9994cb14639f6291f64f479c6 Mon Sep 17 00:00:00 2001 From: neverland Date: Sun, 14 Aug 2022 11:03:49 +0800 Subject: [PATCH] feat(Form): add validateEmpty option of rule (#10913) --- packages/vant/src/field/Field.tsx | 5 ++++ packages/vant/src/field/types.ts | 1 + packages/vant/src/field/utils.ts | 11 +++++-- packages/vant/src/form/README.md | 9 +++--- packages/vant/src/form/README.zh-CN.md | 9 +++--- packages/vant/src/form/test/props.spec.tsx | 34 ++++++++++++++++++++++ 6 files changed, 58 insertions(+), 11 deletions(-) diff --git a/packages/vant/src/field/Field.tsx b/packages/vant/src/field/Field.tsx index 8eb7d2a4f..3d1511638 100644 --- a/packages/vant/src/field/Field.tsx +++ b/packages/vant/src/field/Field.tsx @@ -32,6 +32,7 @@ import { runSyncRule, endComposing, mapInputType, + isEmptyValue, startComposing, getRuleMessage, resizeTextarea, @@ -201,6 +202,10 @@ export default defineComponent({ } if (rule.validator) { + if (isEmptyValue(value) && rule.validateEmpty === false) { + return; + } + return runRuleValidator(value, rule).then((result) => { if (result && typeof result === 'string') { state.status = 'failed'; diff --git a/packages/vant/src/field/types.ts b/packages/vant/src/field/types.ts index 51200e8c8..26283f1aa 100644 --- a/packages/vant/src/field/types.ts +++ b/packages/vant/src/field/types.ts @@ -64,6 +64,7 @@ export type FieldRule = { required?: boolean; validator?: FieldRuleValidator; formatter?: FiledRuleFormatter; + validateEmpty?: boolean; }; export type FieldValidationStatus = 'passed' | 'failed' | 'unvalidated'; diff --git a/packages/vant/src/field/utils.ts b/packages/vant/src/field/utils.ts index 03eeae162..02010a36b 100644 --- a/packages/vant/src/field/utils.ts +++ b/packages/vant/src/field/utils.ts @@ -8,7 +8,7 @@ import { } from '../utils'; import type { FieldRule, FieldType, FieldAutosizeConfig } from './types'; -function isEmptyValue(value: unknown) { +export function isEmptyValue(value: unknown) { if (Array.isArray(value)) { return !value.length; } @@ -19,8 +19,13 @@ function isEmptyValue(value: unknown) { } export function runSyncRule(value: unknown, rule: FieldRule) { - if (rule.required && isEmptyValue(value)) { - return false; + if (isEmptyValue(value)) { + if (rule.required) { + return false; + } + if (rule.validateEmpty === false) { + return true; + } } if (rule.pattern && !rule.pattern.test(String(value))) { return false; diff --git a/packages/vant/src/form/README.md b/packages/vant/src/form/README.md index 4fc9cd3c8..39b96e18d 100644 --- a/packages/vant/src/form/README.md +++ b/packages/vant/src/form/README.md @@ -511,12 +511,13 @@ export default { | Key | Description | Type | | --- | --- | --- | -| required | Whether to be a required field, the value is not allowed to be empty string, empty array, `false`, `undefined`, `null` | _boolean_ | -| message | Error message | _string \| (value, rule) => string_ | -| validator | Custom validator | _(value, rule) => boolean \| string \| Promise_ | -| pattern | Regex pattern | _RegExp_ | +| required | Whether to be a required field, the value is not allowed to be empty (empty string, empty array, `false`, `undefined`, `null`) | _boolean_ | +| message | Error message, can be a function to dynamically return message content | _string \| (value, rule) => string_ | +| validator | Custom validator, can return a Promise to validate dynamically | _(value, rule) => boolean \| string \| Promise_ | +| pattern | Regexp pattern, if the regexp cannot match, means that the validation fails | _RegExp_ | | trigger | When to validate the form, priority is higher than the `validate-trigger` of the Form component, can be set to `onChange`, `onBlur`, `onSubmit` | _string \| string[]_ | | formatter | Format value before validate | _(value, rule) => any_ | +| validateEmpty `v3.6.0` | Controls whether the `validator` and `pattern` options to verify empty values, the default value is `true`, you can set to `false` to disable this behavior | _boolean_ | ### validate-trigger diff --git a/packages/vant/src/form/README.zh-CN.md b/packages/vant/src/form/README.zh-CN.md index 6b7c0b8ef..bbdf41958 100644 --- a/packages/vant/src/form/README.zh-CN.md +++ b/packages/vant/src/form/README.zh-CN.md @@ -547,12 +547,13 @@ export default { | 键名 | 说明 | 类型 | | --- | --- | --- | -| required | 是否为必选字段,当值为空字符串、空数组、`false`、`undefined`、`null` 时,校验不通过 | _boolean_ | -| message | 错误提示文案 | _string \| (value, rule) => string_ | -| validator | 通过函数进行校验 | _(value, rule) => boolean \| string \| Promise_ | -| pattern | 通过正则表达式进行校验 | _RegExp_ | +| required | 是否为必选字段,当值为空值时(空字符串、空数组、`false`、`undefined`、`null` ),校验不通过 | _boolean_ | +| message | 错误提示文案,可以设置为一个函数来返回动态的文案内容 | _string \| (value, rule) => string_ | +| validator | 通过函数进行校验,可以返回一个 Promise 来进行异步校验 | _(value, rule) => boolean \| string \| Promise_ | +| pattern | 通过正则表达式进行校验,正则无法匹配表示校验不通过 | _RegExp_ | | trigger | 设置本项规则的触发时机,优先级高于 Form 组件设置的 `validate-trigger` 属性,可选值为 `onChange`、`onBlur`、`onSubmit` | _string \| string[]_ | | formatter | 格式化函数,将表单项的值转换后进行校验 | _(value, rule) => any_ | +| validateEmpty `v3.6.0` | 设置 `validator` 和 `pattern` 是否要对空值进行校验,默认值为 `true`,可以设置为 `false` 来禁用该行为 | _boolean_ | ### validate-trigger 可选值 diff --git a/packages/vant/src/form/test/props.spec.tsx b/packages/vant/src/form/test/props.spec.tsx index 1c4be2535..ee9232879 100644 --- a/packages/vant/src/form/test/props.spec.tsx +++ b/packages/vant/src/form/test/props.spec.tsx @@ -70,6 +70,40 @@ test('should support message function in rules prop', async () => { }); }); +test('should skip pattern if validateEmpty is false in rules prop', async () => { + const onFailed = jest.fn(); + const rules: FieldRule[] = [{ pattern: /\d{6}/, validateEmpty: false }]; + const wrapper = mount({ + render() { + return ( +
+ + + ); + }, + }); + + await submitForm(wrapper); + expect(onFailed).toHaveBeenCalledTimes(0); +}); + +test('should skip validator if validateEmpty is false in rules prop', async () => { + const onFailed = jest.fn(); + const rules: FieldRule[] = [{ validator: () => false, validateEmpty: false }]; + const wrapper = mount({ + render() { + return ( +
+ + + ); + }, + }); + + await submitForm(wrapper); + expect(onFailed).toHaveBeenCalledTimes(0); +}); + test('should support formatter in rules prop', async () => { const onFailed = jest.fn(); const rules: FieldRule[] = [