vue3-form-validation
Advanced tools
Comparing version 3.0.3 to 3.0.4
import { Ref, ComputedRef, UnwrapRef } from 'vue'; | ||
import Form from '../Form'; | ||
export declare type SimpleRule<T = any> = (value: T) => Promise<unknown> | unknown; | ||
export declare type SimpleRule<T = any> = (value: T) => any; | ||
export declare type KeyedRule<T = any> = { | ||
@@ -5,0 +5,0 @@ key: string; |
@@ -1,2 +0,2 @@ | ||
import { reactive, watch, ref } from 'vue'; | ||
import { reactive, watch } from 'vue'; | ||
import useUid from './useUid'; | ||
@@ -30,5 +30,5 @@ import Form from '../Form'; | ||
}); | ||
watch(formField.modelValue, async () => { | ||
watch(formField.modelValue, () => { | ||
if (formField.touched) { | ||
await form.validate(uid); | ||
form.validate(uid); | ||
} | ||
@@ -57,3 +57,6 @@ }); | ||
if (isTransformedField(value)) { | ||
resultFormData[key] = value.$value; | ||
resultFormData[key] = | ||
typeof value.$value === 'object' | ||
? JSON.parse(JSON.stringify(value.$value)) | ||
: value.$value; | ||
return; | ||
@@ -96,3 +99,2 @@ } | ||
const form = new Form(); | ||
const submitting = ref(false); | ||
const promiseCancel = new PromiseCancel(); | ||
@@ -103,18 +105,17 @@ transformFormData(form, formData); | ||
form: transformedFormData, | ||
submitting, | ||
submitting: form.submitting, | ||
errors: form.getErrors(), | ||
async validateFields() { | ||
submitting.value = true; | ||
form.submitting.value = true; | ||
const resultFormData = {}; | ||
getResultFormData(transformedFormData, resultFormData); | ||
const hasError = await promiseCancel.race(form.validateAll()); | ||
form.submitting.value = false; | ||
if (hasError) { | ||
submitting.value = false; | ||
throw undefined; | ||
} | ||
const resultFormData = {}; | ||
getResultFormData(transformedFormData, resultFormData); | ||
submitting.value = false; | ||
return resultFormData; | ||
}, | ||
async resetFields() { | ||
if (submitting.value) { | ||
if (form.submitting.value) { | ||
promiseCancel.cancelResolve(true); | ||
@@ -121,0 +122,0 @@ } |
@@ -11,2 +11,3 @@ import { Rule } from './composable/useValidation'; | ||
private tryGetKeyed; | ||
submitting: import("vue").Ref<boolean>; | ||
registerField(uid: number, rules: Rule[], modelValue?: unknown): FormField; | ||
@@ -18,3 +19,3 @@ getErrors(): import("vue").ComputedRef<string[]>; | ||
onDelete(uid: number): void; | ||
private getValidateResultsFor; | ||
private getPromisesFor; | ||
private isEveryFormFieldTouchedWith; | ||
@@ -21,0 +22,0 @@ private makeValidate; |
@@ -1,4 +0,4 @@ | ||
import { computed, reactive, unref } from 'vue'; | ||
import { computed, reactive, ref, unref } from 'vue'; | ||
import FormField from './FormField'; | ||
import { tryGet, trySet } from './utils'; | ||
import { PromiseCancel, tryGet, trySet } from './utils'; | ||
const isSimpleRule = (rule) => typeof rule === 'function'; | ||
@@ -13,7 +13,8 @@ export default class Form { | ||
this.tryGetKeyed = tryGet(this.keyedValidators); | ||
this.submitting = ref(false); | ||
} | ||
registerField(uid, rules, modelValue) { | ||
const formField = new FormField(rules, modelValue); | ||
const simple = rules.reduce((simple, rule, index) => { | ||
const validate = this.makeValidate(formField, rule, index); | ||
const simple = rules.reduce((simple, rule, ruleNumber) => { | ||
const validate = this.makeValidate(formField, rule, ruleNumber); | ||
if (isSimpleRule(rule)) { | ||
@@ -65,17 +66,18 @@ simple.validators.push(validate); | ||
async validateAll() { | ||
for (const { formField } of this.simpleValidators.values()) { | ||
formField.touched = false; | ||
const promises = []; | ||
for (const { formField, validators } of this.simpleValidators.values()) { | ||
formField.touched = true; | ||
promises.push(...validators.map(v => v())); | ||
} | ||
const promises = [...this.simpleValidators.entries()].map(([uid, { formField }]) => { | ||
formField.touched = true; | ||
return this.validate(uid); | ||
}); | ||
const allSettledResults = await Promise.all(promises); | ||
for (const settledResults of allSettledResults) { | ||
for (const settledResult of settledResults) { | ||
if (settledResult.status === 'rejected') { | ||
return true; | ||
} | ||
for (const keyed of this.keyedValidators.values()) { | ||
for (const { validator } of keyed) { | ||
promises.push(validator()); | ||
} | ||
} | ||
const settledResult = await Promise.allSettled(promises); | ||
for (const result of settledResult) { | ||
if (result.status === 'rejected') { | ||
return true; | ||
} | ||
} | ||
return false; | ||
@@ -90,3 +92,3 @@ } | ||
...validators.map(v => v()), | ||
...this.getValidateResultsFor(keys) | ||
...this.getPromisesFor(keys) | ||
]); | ||
@@ -107,3 +109,3 @@ } | ||
} | ||
getValidateResultsFor(keys) { | ||
getPromisesFor(keys) { | ||
return keys.reduce((promises, key) => { | ||
@@ -134,27 +136,34 @@ this.tryGetKeyed({ | ||
} | ||
makeValidate(formField, rule, index) { | ||
const validator = formField => (index, rule) => async () => { | ||
makeValidate(formField, rule, ruleNumber) { | ||
const validator = formField => (rule, ruleNumber, promiseCancel) => async () => { | ||
let error; | ||
try { | ||
formField.incrementWaiting(index); | ||
error = await rule(unref(formField.modelValue)); | ||
const ruleResult = rule(unref(formField.modelValue)); | ||
if (typeof (ruleResult === null || ruleResult === void 0 ? void 0 : ruleResult.then) === 'function') { | ||
try { | ||
formField.rulesValidating.value++; | ||
if (!this.submitting.value) { | ||
promiseCancel.cancelResolve(null); | ||
} | ||
error = await promiseCancel.race(ruleResult); | ||
} | ||
catch (err) { | ||
error = err; | ||
} | ||
finally { | ||
formField.rulesValidating.value--; | ||
} | ||
} | ||
catch (err) { | ||
error = err; | ||
else { | ||
error = ruleResult; | ||
} | ||
finally { | ||
formField.decrementWaiting(index); | ||
if (typeof error === 'string' && formField.touched) { | ||
formField.setError(ruleNumber, error); | ||
throw error; | ||
} | ||
if (formField.nooneIsWaiting(index) && formField.touched) { | ||
if (typeof error === 'string') { | ||
formField.setError(index, error); | ||
throw error; | ||
} | ||
else { | ||
formField.setError(index, null); | ||
} | ||
else { | ||
formField.setError(ruleNumber, null); | ||
} | ||
}; | ||
return validator(formField)(index, isSimpleRule(rule) ? rule : rule.rule); | ||
return validator(formField)(isSimpleRule(rule) ? rule : rule.rule, ruleNumber, new PromiseCancel()); | ||
} | ||
} |
@@ -5,5 +5,3 @@ import { reactive, ref } from 'vue'; | ||
private errors; | ||
private waiting; | ||
private totalWaiting; | ||
private errorCount; | ||
rulesValidating: import("vue").Ref<number>; | ||
modelValue: ReturnType<typeof ref> | ReturnType<typeof reactive>; | ||
@@ -13,7 +11,3 @@ private initialModelValue; | ||
constructor(rules: Rule[], modelValue: unknown); | ||
setError(index: number, error: string | null): void; | ||
incrementWaiting(index: number): void; | ||
decrementWaiting(index: number): void; | ||
nooneIsWaiting(index: number): boolean; | ||
hasError(): boolean; | ||
setError(ruleNumber: number, error: string | null): void; | ||
getErrors(): import("vue").ComputedRef<string[]>; | ||
@@ -20,0 +14,0 @@ validating(): import("vue").ComputedRef<boolean>; |
@@ -5,7 +5,5 @@ import { computed, isRef, reactive, ref } from 'vue'; | ||
constructor(rules, modelValue) { | ||
this.totalWaiting = ref(0); | ||
this.errorCount = 0; | ||
this.rulesValidating = ref(0); | ||
this.touched = false; | ||
this.errors = reactive(rules.map(() => null)); | ||
this.waiting = rules.map(() => 0); | ||
if (isRef(modelValue)) { | ||
@@ -26,26 +24,5 @@ this.modelValue = modelValue; | ||
} | ||
setError(index, error) { | ||
const willBeSet = this.errors[index]; | ||
if (willBeSet === null && typeof error === 'string') { | ||
this.errorCount++; | ||
} | ||
if (typeof willBeSet === 'string' && error === null) { | ||
this.errorCount--; | ||
} | ||
this.errors[index] = error; | ||
setError(ruleNumber, error) { | ||
this.errors[ruleNumber] = error; | ||
} | ||
incrementWaiting(index) { | ||
this.totalWaiting.value++; | ||
this.waiting[index]++; | ||
} | ||
decrementWaiting(index) { | ||
this.totalWaiting.value--; | ||
this.waiting[index]--; | ||
} | ||
nooneIsWaiting(index) { | ||
return this.waiting[index] === 0; | ||
} | ||
hasError() { | ||
return this.errorCount > 0; | ||
} | ||
getErrors() { | ||
@@ -55,3 +32,3 @@ return computed(() => this.errors.filter(notNull)); | ||
validating() { | ||
return computed(() => this.totalWaiting.value > 0); | ||
return computed(() => this.rulesValidating.value > 0); | ||
} | ||
@@ -68,4 +45,3 @@ reset() { | ||
Object.assign(this.errors, this.errors.map(() => null)); | ||
this.errorCount = 0; | ||
} | ||
} |
@@ -1,5 +0,6 @@ | ||
export declare class PromiseCancel<T> { | ||
export declare class PromiseCancel<T = unknown> { | ||
private promise; | ||
private _resolve; | ||
private _reject; | ||
private resolve; | ||
private reject; | ||
private raceHasBeenCalled; | ||
constructor(); | ||
@@ -6,0 +7,0 @@ cancelResolve(value: T | PromiseLike<T>): void; |
export class PromiseCancel { | ||
constructor() { | ||
this.raceHasBeenCalled = false; | ||
this.assign(); | ||
} | ||
cancelResolve(value) { | ||
this._resolve(value); | ||
this.assign(); | ||
if (this.raceHasBeenCalled) { | ||
this.resolve(value); | ||
this.assign(); | ||
} | ||
} | ||
cancelReject(reason) { | ||
this._reject(reason); | ||
this.assign(); | ||
if (this.raceHasBeenCalled) { | ||
this.reject(reason); | ||
this.assign(); | ||
} | ||
} | ||
race(...promises) { | ||
this.raceHasBeenCalled = true; | ||
return Promise.race([this.promise, ...promises]); | ||
@@ -18,6 +24,6 @@ } | ||
this.promise = new Promise((resolve, reject) => { | ||
this._resolve = resolve; | ||
this._reject = reject; | ||
this.resolve = resolve; | ||
this.reject = reject; | ||
}); | ||
} | ||
} |
{ | ||
"name": "vue3-form-validation", | ||
"version": "3.0.3", | ||
"version": "3.0.4", | ||
"description": "Vue composition function for Form Validation", | ||
@@ -5,0 +5,0 @@ "author": { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
30329
546