Skip to content

Commit fc82886

Browse files
committed
[2.2.0] Run asyncValidators only on blur event
1 parent cd5293a commit fc82886

File tree

9 files changed

+94
-53
lines changed

9 files changed

+94
-53
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
## 2.2.0
2+
3+
### Changed
4+
5+
- `asyncValidators` will be called only on `blur` event
6+
- As before, they will be called only if there is no sync errors
7+
18
## 2.1.0
29

310
### Added

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ See demo at [https://detools.github.io/vue-form](https://detools.github.io/vue-f
7878

7979
## Changelog
8080

81+
- [2.2.0](/CHANGELOG.md#220)
8182
- [2.1.0](/CHANGELOG.md#210)
8283
- [2.0.0](/CHANGELOG.md#200)
8384
- [1.5.0](/CHANGELOG.md#150)

VueForm/ConnectedInput.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,9 @@ export default {
7878
handleFieldBlur(...args) {
7979
this.touched = true
8080

81-
this.handleBlur(...args)
81+
const onBlur = () => this.handleBlur(...args)
82+
83+
return this.setAsyncError().then(onBlur, onBlur)
8284
},
8385

8486
renderInput(value, setValue) {

VueForm/Form.vue

Lines changed: 54 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Form, Button } from 'element-ui'
44
import FormItem from './ConnectedFormItem'
55
import Notification from './Notification'
66
import CONSTANTS from './constants'
7-
import validate from './validators/validate'
7+
import { validate, asyncValidate } from './validators/validate'
88
99
const BUTTONS_POSITION = {
1010
START: 'start',
@@ -43,6 +43,10 @@ export default {
4343
handleModelChange: Function,
4444
handleDisabled: Function,
4545
handleReset: Function,
46+
47+
validate: Function,
48+
asyncValidate: Function,
49+
asyncBlurFields: Array,
4650
},
4751
4852
data() {
@@ -51,6 +55,7 @@ export default {
5155
errors: {},
5256
form: {
5357
submitting: false,
58+
validating: false,
5459
},
5560
}
5661
},
@@ -81,35 +86,33 @@ export default {
8186
const value = !isNil(formLevelInitialValue) ? formLevelInitialValue : fieldLevelInitialValue
8287
8388
const setError = nextValue => {
84-
let validatorsPromise = Promise.resolve()
85-
let syncError = false
86-
87-
const on = {
88-
success: () => vm.$delete(vm.errors, name),
89-
error: error => {
90-
if (error) {
91-
vm.$set(vm.errors, name, error)
92-
}
93-
},
94-
}
95-
9689
if (validators) {
97-
validatorsPromise = validate(validators, nextValue, name)
98-
.then(on.success)
99-
.catch(error => {
100-
on.error(error)
101-
syncError = true
102-
})
90+
const offValidating = this.manageValidatingState()
91+
const error = validate(validators, nextValue, name)
92+
offValidating()
93+
94+
const method = error ? vm.$set : vm.$delete
95+
96+
method(vm.errors, name, error)
10397
}
98+
}
99+
100+
const on = {
101+
success: () => vm.$delete(vm.errors, name),
102+
error: error => vm.$set(vm.errors, name, error),
103+
}
104104
105-
if (asyncValidators) {
106-
validatorsPromise
107-
// Prevent async validation when we have sync errors
108-
.then(() => syncError && Promise.reject())
109-
.then(() => validate(asyncValidators, nextValue, name))
105+
const setAsyncError = () => {
106+
if (!this.errors[name] && asyncValidators) {
107+
const offValidating = this.manageValidatingState()
108+
109+
return asyncValidate(asyncValidators, this.state[name], name)
110110
.then(on.success)
111111
.catch(on.error)
112+
.then(offValidating)
112113
}
114+
115+
return Promise.resolve()
113116
}
114117
115118
const setValue = nextValue => {
@@ -134,10 +137,19 @@ export default {
134137
return {
135138
cleanFormValue,
136139
setError,
140+
setAsyncError,
137141
useState: () => [this.state[name], setValue, this.errors[name]],
138142
}
139143
},
140144
145+
manageValidatingState() {
146+
this.form.validating = true
147+
148+
return () => {
149+
this.form.validating = false
150+
}
151+
},
152+
141153
manageSubmittingState() {
142154
this.form.submitting = true
143155
@@ -158,12 +170,17 @@ export default {
158170
159171
const messages = this.messages || {}
160172
const off = this.manageSubmittingState()
161-
return Promise.resolve(this.handleSubmit({ ...this.initialValues, ...this.state }))
162-
.then(
163-
() => Notification.success(messages.success),
164-
() => Notification.error(messages.error)
165-
)
166-
.then(off)
173+
const submitPromise = Promise.resolve(
174+
this.handleSubmit({ ...this.initialValues, ...this.state })
175+
)
176+
177+
// Just subscribe to promise, do not catch errors
178+
submitPromise.then(
179+
() => Notification.success(messages.success),
180+
() => Notification.error(messages.error)
181+
).then(off)
182+
183+
return submitPromise
167184
},
168185
169186
nativeOnReset(event) {
@@ -202,23 +219,27 @@ export default {
202219
},
203220
]
204221
222+
const { submitting, validating } = this.form
223+
const disabled = submitting || validating
224+
const submitDisabled = disabled || (!this.isValid && !this.handleDisabled)
225+
205226
return (
206227
<div class={buttonsClassName}>
207228
{this.reset && (
208-
<Button nativeType="reset" disabled={this.form.submitting}>
229+
<Button nativeType="reset" disabled={disabled}>
209230
{buttons.reset}
210231
</Button>
211232
)}
212233
{this.save && (
213-
<Button nativeType="submit" type="primary" disabled={this.form.submitting}>
234+
<Button nativeType="submit" type="primary" disabled={disabled}>
214235
{buttons.save}
215236
</Button>
216237
)}
217238
{this.submit && (
218239
<Button
219240
type={this.save ? 'danger' : 'primary'}
220241
nativeType={!this.save ? 'submit' : undefined}
221-
disabled={(!this.isValid && !this.handleDisabled) || this.form.submitting}
242+
disabled={submitDisabled}
222243
on-click={this.nativeOnSubmit}>
223244
{buttons.submit}
224245
</Button>

VueForm/validators/validate.js

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,31 @@
11
import noop from 'lodash/noop'
22
import invariant from 'invariant'
3-
import isPromise from '../utils/is-promise'
43

5-
export default function validate(validators, value, name) {
4+
export const validate = function validate(validators, value, name) {
65
invariant(Array.isArray(validators), '"validate" accepts an array of validators')
76

8-
return validators.reduce(
9-
(sequence, validator = noop) =>
10-
sequence.then(() => {
11-
const result = validator(value, name)
7+
let error
8+
let i = 0
9+
const { length } = validators
10+
11+
for (i; i < length; i += 1) {
12+
const validator = validators[i] || noop
13+
const errorString = validator(value, name)
1214

13-
if (isPromise(result)) {
14-
return result
15-
}
15+
if (errorString) {
16+
error = errorString
17+
break
18+
}
19+
}
20+
21+
return error
22+
}
1623

17-
return result ? Promise.reject(result) : Promise.resolve()
18-
}),
24+
export const asyncValidate = function asyncValidate(validators, value, name) {
25+
invariant(Array.isArray(validators), '"validate" accepts an array of validators')
26+
27+
return validators.reduce(
28+
(sequence, validator = noop) => sequence.then(() => validator(value, name)),
1929
Promise.resolve()
2030
)
2131
}

docs/bundle.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/main.css

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,17 @@
1212
}
1313

1414

15-
.buttons[data-v-98b83d4a] {
15+
.buttons[data-v-929e2c82] {
1616
display: flex;
1717
flex-direction: row;
1818
flex-wrap: no-wrap;
1919
justify-content: flex-start;
2020
align-items: flex-start;
2121
}
22-
.buttons_center[data-v-98b83d4a] {
22+
.buttons_center[data-v-929e2c82] {
2323
justify-content: center;
2424
}
25-
.buttons_end[data-v-98b83d4a] {
25+
.buttons_end[data-v-929e2c82] {
2626
justify-content: flex-end;
2727
}
2828

docs/vendors~main.bundle.js

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@detools/vue-form",
3-
"version": "2.1.0",
3+
"version": "2.2.0",
44
"description": "Vue Form component on hooks",
55
"main": "VueForm/index.js",
66
"scripts": {

0 commit comments

Comments
 (0)