From c08db724a3ed6440da5d5faebfa08561312f4d3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=98=89=E6=B6=B5?= Date: Wed, 19 Feb 2020 17:25:30 +0800 Subject: [PATCH] feat(Form): add validate-trigger prop --- src/field/index.js | 27 +++++++++++++++---- src/form/README.md | 1 + src/form/README.zh-CN.md | 1 + src/form/index.js | 4 +++ src/form/test/props.spec.js | 52 +++++++++++++++++++++++++++++++++++++ src/mixins/field.js | 13 +++++++--- 6 files changed, 89 insertions(+), 9 deletions(-) diff --git a/src/field/index.js b/src/field/index.js index 31a04aada..25806d111 100644 --- a/src/field/index.js +++ b/src/field/index.js @@ -64,6 +64,7 @@ export default createComponent({ watch: { value() { this.resetValidation(); + this.validateWithTrigger('onChange'); this.$nextTick(this.adjustSize); }, }, @@ -158,8 +159,8 @@ export default createComponent({ }); }, - runRules() { - return this.rules.reduce( + runRules(rules) { + return rules.reduce( (promise, rule) => promise.then(() => { if (this.validateMessage) { @@ -183,13 +184,13 @@ export default createComponent({ ); }, - validate() { + validate(rules = this.rules) { return new Promise(resolve => { - if (!this.rules) { + if (!rules) { resolve(); } - this.runRules().then(() => { + this.runRules(rules).then(() => { if (this.validateMessage) { resolve({ name: this.name, @@ -202,6 +203,21 @@ export default createComponent({ }); }, + validateWithTrigger(trigger) { + if (this.vanForm && this.rules) { + const defaultTrigger = this.vanForm.validateTrigger === trigger; + const rules = this.rules.filter(rule => { + if (rule.trigger) { + return rule.trigger === trigger; + } + + return defaultTrigger; + }); + + this.validate(rules); + } + }, + resetValidation() { if (this.validateMessage) { this.validateMessage = ''; @@ -269,6 +285,7 @@ export default createComponent({ onBlur(event) { this.focused = false; this.$emit('blur', event); + this.validateWithTrigger('onBlur'); resetScroll(); }, diff --git a/src/form/README.md b/src/form/README.md index fd87bdc48..e944c4e89 100644 --- a/src/form/README.md +++ b/src/form/README.md @@ -411,6 +411,7 @@ export default { | error-message-align | Error message align, can be set to `center` `right` | *string* | `left` | | colon | Whether to display `:` after label | *boolean* | *false* | | validate-first | Whether to stop the validation when a rule fails | *boolean* | `false` | +| validate-trigger `v2.5.2` | When to validate the form,can be set to `onChange`、`onSubmit` | *string* | `onBlur` | ### Events diff --git a/src/form/README.zh-CN.md b/src/form/README.zh-CN.md index 71e1bed87..54375a894 100644 --- a/src/form/README.zh-CN.md +++ b/src/form/README.zh-CN.md @@ -443,6 +443,7 @@ export default { | error-message-align | 错误提示文案对齐方式,可选值为 `center` `right` | *string* | `left` | | colon | 是否在 label 后面添加冒号 | *boolean* | *false* | | validate-first | 是否在某一项校验不通过时停止校验 | *boolean* | `false` | +| validate-trigger `v2.5.2` | 表单校验触发时机,可选值为`onChange`、`onSubmit` | *string* | `onBlur` | > 表单项的 API 参见:[Field 组件](#/zh-CN/field#api) diff --git a/src/form/index.js b/src/form/index.js index 11822c8fb..29a7b621c 100644 --- a/src/form/index.js +++ b/src/form/index.js @@ -10,6 +10,10 @@ export default createComponent({ inputAlign: String, validateFirst: Boolean, errorMessageAlign: String, + validateTrigger: { + type: String, + default: 'onBlur', + }, }, provide() { diff --git a/src/form/test/props.spec.js b/src/form/test/props.spec.js index 0e56ee28a..15f8409b8 100644 --- a/src/form/test/props.spec.js +++ b/src/form/test/props.spec.js @@ -1,3 +1,4 @@ +import { later } from '../../../test'; import { mountForm, submitForm, getSimpleRules } from './shared'; test('rules prop - execute order', async () => { @@ -167,3 +168,54 @@ test('error-message-align prop', () => { }); expect(wrapper).toMatchSnapshot(); }); + +test('validate-trigger - onBlur', async () => { + const wrapper = mountForm({ + template: ` + + + + `, + data: getSimpleRules, + }); + + const input = wrapper.find('input'); + + input.trigger('input'); + await later(); + expect(wrapper.contains('.van-field__error-message')).toBeFalsy(); + + input.trigger('blur'); + await later(); + expect(wrapper.contains('.van-field__error-message')).toBeTruthy(); +}); + +test('validate-trigger - onChange', async () => { + const wrapper = mountForm({ + template: ` + + + + `, + data() { + return { + ...getSimpleRules(), + value: '', + }; + }, + }); + + const input = wrapper.find('input'); + + input.trigger('blur'); + await later(); + expect(wrapper.contains('.van-field__error-message')).toBeFalsy(); + + wrapper.setData({ value: '1' }); + await later(); + expect(wrapper.contains('.van-field__error-message')).toBeFalsy(); + + wrapper.setData({ value: '' }); + await later(); + expect(wrapper.contains('.van-field__error-message')).toBeTruthy(); +}); diff --git a/src/mixins/field.js b/src/mixins/field.js index ece4421df..603cff7da 100644 --- a/src/mixins/field.js +++ b/src/mixins/field.js @@ -7,15 +7,20 @@ export const FieldMixin = { watch: { value() { - if (this.vanField) { - this.vanField.resetValidation(); + const field = this.vanField; + + if (field) { + field.resetValidation(); + field.validateWithTrigger('onChange'); } }, }, created() { - if (this.vanField && !this.vanField.children) { - this.vanField.children = this; + const field = this.vanField; + + if (field && !field.children) { + field.children = this; } }, };