@tanstack/form-core
Advanced tools
Comparing version 0.10.2 to 0.10.3
@@ -108,3 +108,3 @@ // src/FieldApi.ts | ||
}; | ||
let hasError = false; | ||
let hasErrored = false; | ||
this.form.store.batch(() => { | ||
@@ -124,8 +124,10 @@ for (const validateObj of validates) { | ||
})); | ||
hasError = true; | ||
} | ||
if (error) { | ||
hasErrored = true; | ||
} | ||
} | ||
}); | ||
const submitErrKey = getErrorMapKey("submit"); | ||
if (this.state.meta.errorMap[submitErrKey] && cause !== "submit" && !hasError) { | ||
if (this.state.meta.errorMap[submitErrKey] && cause !== "submit" && !hasErrored) { | ||
this.setMeta((prev) => ({ | ||
@@ -139,5 +141,6 @@ ...prev, | ||
} | ||
if (hasError) { | ||
if (hasErrored) { | ||
this.cancelValidateAsync(); | ||
} | ||
return { hasErrored }; | ||
}; | ||
@@ -236,7 +239,4 @@ this.__leaseValidateAsync = () => { | ||
} | ||
const errorMapKey = getErrorMapKey(cause); | ||
const prevError = this.getMeta().errorMap[errorMapKey]; | ||
this.validateSync(value, cause); | ||
const newError = this.getMeta().errorMap[errorMapKey]; | ||
if (prevError !== newError) { | ||
const { hasErrored } = this.validateSync(value, cause); | ||
if (hasErrored) { | ||
if (!this.options.asyncAlways) { | ||
@@ -243,0 +243,0 @@ return this.state.meta.errors; |
@@ -96,7 +96,7 @@ // src/FormApi.ts | ||
Object.values(field.instances).forEach((instance) => { | ||
fieldValidationPromises.push( | ||
Promise.resolve().then(() => instance.validate(cause)) | ||
); | ||
if (!instance.state.meta.isTouched) { | ||
instance.setMeta((prev) => ({ ...prev, isTouched: true })); | ||
fieldValidationPromises.push( | ||
Promise.resolve().then(() => instance.validate(cause)) | ||
); | ||
} | ||
@@ -103,0 +103,0 @@ }); |
@@ -159,3 +159,5 @@ import { Store } from '@tanstack/store'; | ||
getSubField: <TSubName extends DeepKeys<TData>, TSubData extends DeepValue<TData, TSubName> = DeepValue<TData, TSubName>>(name: TSubName) => FieldApi<TData, TSubName, ValidatorType, TSubData, DeepValue<TData, TSubName>>; | ||
validateSync: (value: TData | undefined, cause: ValidationCause) => void; | ||
validateSync: (value: TData | undefined, cause: ValidationCause) => { | ||
hasErrored: boolean; | ||
}; | ||
__leaseValidateAsync: () => number; | ||
@@ -162,0 +164,0 @@ cancelValidateAsync: () => void; |
@@ -106,3 +106,3 @@ // src/FieldApi.ts | ||
}; | ||
let hasError = false; | ||
let hasErrored = false; | ||
this.form.store.batch(() => { | ||
@@ -122,8 +122,10 @@ for (const validateObj of validates) { | ||
})); | ||
hasError = true; | ||
} | ||
if (error) { | ||
hasErrored = true; | ||
} | ||
} | ||
}); | ||
const submitErrKey = getErrorMapKey("submit"); | ||
if (this.state.meta.errorMap[submitErrKey] && cause !== "submit" && !hasError) { | ||
if (this.state.meta.errorMap[submitErrKey] && cause !== "submit" && !hasErrored) { | ||
this.setMeta((prev) => ({ | ||
@@ -137,5 +139,6 @@ ...prev, | ||
} | ||
if (hasError) { | ||
if (hasErrored) { | ||
this.cancelValidateAsync(); | ||
} | ||
return { hasErrored }; | ||
}; | ||
@@ -233,7 +236,4 @@ this.__leaseValidateAsync = () => { | ||
} | ||
const errorMapKey = getErrorMapKey(cause); | ||
const prevError = this.getMeta().errorMap[errorMapKey]; | ||
this.validateSync(value, cause); | ||
const newError = this.getMeta().errorMap[errorMapKey]; | ||
if (prevError !== newError) { | ||
const { hasErrored } = this.validateSync(value, cause); | ||
if (hasErrored) { | ||
if (!this.options.asyncAlways) { | ||
@@ -240,0 +240,0 @@ return this.state.meta.errors; |
@@ -93,7 +93,7 @@ // src/FormApi.ts | ||
Object.values(field.instances).forEach((instance) => { | ||
fieldValidationPromises.push( | ||
Promise.resolve().then(() => instance.validate(cause)) | ||
); | ||
if (!instance.state.meta.isTouched) { | ||
instance.setMeta((prev) => ({ ...prev, isTouched: true })); | ||
fieldValidationPromises.push( | ||
Promise.resolve().then(() => instance.validate(cause)) | ||
); | ||
} | ||
@@ -100,0 +100,0 @@ }); |
@@ -159,3 +159,5 @@ import { Store } from '@tanstack/store'; | ||
getSubField: <TSubName extends DeepKeys<TData>, TSubData extends DeepValue<TData, TSubName> = DeepValue<TData, TSubName>>(name: TSubName) => FieldApi<TData, TSubName, ValidatorType, TSubData, DeepValue<TData, TSubName>>; | ||
validateSync: (value: TData | undefined, cause: ValidationCause) => void; | ||
validateSync: (value: TData | undefined, cause: ValidationCause) => { | ||
hasErrored: boolean; | ||
}; | ||
__leaseValidateAsync: () => number; | ||
@@ -162,0 +164,0 @@ cancelValidateAsync: () => void; |
{ | ||
"name": "@tanstack/form-core", | ||
"version": "0.10.2", | ||
"version": "0.10.3", | ||
"description": "Powerful, type-safe, framework agnostic forms.", | ||
@@ -5,0 +5,0 @@ "author": "tannerlinsley", |
@@ -381,3 +381,3 @@ import { Store } from '@tanstack/store' | ||
// Needs type cast as eslint errantly believes this is always falsy | ||
let hasError = false as boolean | ||
let hasErrored = false as boolean | ||
@@ -397,4 +397,6 @@ this.form.store.batch(() => { | ||
})) | ||
hasError = true | ||
} | ||
if (error) { | ||
hasErrored = true | ||
} | ||
} | ||
@@ -411,3 +413,3 @@ }) | ||
cause !== 'submit' && | ||
!hasError | ||
!hasErrored | ||
) { | ||
@@ -424,5 +426,7 @@ this.setMeta((prev) => ({ | ||
// If a sync error is encountered for the errorMapKey (eg. onChange), cancel any async validation | ||
if (hasError) { | ||
if (hasErrored) { | ||
this.cancelValidateAsync() | ||
} | ||
return { hasErrored } | ||
} | ||
@@ -559,13 +563,6 @@ | ||
// Store the previous error for the errorMapKey (eg. onChange, onBlur, onSubmit) | ||
const errorMapKey = getErrorMapKey(cause) | ||
const prevError = this.getMeta().errorMap[errorMapKey] | ||
// Attempt to sync validate first | ||
this.validateSync(value, cause) | ||
const { hasErrored } = this.validateSync(value, cause) | ||
// If there is a new error mapped to the errorMapKey (eg. onChange, onBlur, onSubmit), return the errors array, do not attempt async validation | ||
const newError = this.getMeta().errorMap[errorMapKey] | ||
if (prevError !== newError) { | ||
if (hasErrored) { | ||
if (!this.options.asyncAlways) { | ||
@@ -572,0 +569,0 @@ return this.state.meta.errors |
@@ -259,2 +259,6 @@ import { Store } from '@tanstack/store' | ||
Object.values(field.instances).forEach((instance) => { | ||
// Validate the field | ||
fieldValidationPromises.push( | ||
Promise.resolve().then(() => instance.validate(cause)), | ||
) | ||
// If any fields are not touched | ||
@@ -264,6 +268,2 @@ if (!instance.state.meta.isTouched) { | ||
instance.setMeta((prev) => ({ ...prev, isTouched: true })) | ||
// Validate the field | ||
fieldValidationPromises.push( | ||
Promise.resolve().then(() => instance.validate(cause)), | ||
) | ||
} | ||
@@ -270,0 +270,0 @@ }) |
@@ -819,2 +819,25 @@ import { expect } from 'vitest' | ||
}) | ||
it('should validate all fields consistently', async () => { | ||
const form = new FormApi({ | ||
defaultValues: { | ||
firstName: '', | ||
lastName: '', | ||
}, | ||
}) | ||
const field = new FieldApi({ | ||
form, | ||
name: 'firstName', | ||
onChange: (v) => (v.length > 0 ? undefined : 'first name is required'), | ||
}) | ||
field.mount() | ||
form.mount() | ||
await form.validateAllFields('change') | ||
expect(field.getMeta().errorMap.onChange).toEqual('first name is required') | ||
await form.validateAllFields('change') | ||
expect(field.getMeta().errorMap.onChange).toEqual('first name is required') | ||
}) | ||
}) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
6685
500557