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;
}
},
};