Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@tanstack/form-core

Package Overview
Dependencies
Maintainers
2
Versions
217
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tanstack/form-core - npm Package Compare versions

Comparing version
1.27.0
to
1.27.1
+45
-51
dist/cjs/FieldApi.cjs

@@ -413,2 +413,11 @@ "use strict";

};
this.setErrorMap = (errorMap) => {
this.setMeta((prev) => ({
...prev,
errorMap: {
...prev.errorMap,
...errorMap
}
}));
};
this.parseValueWithSchema = (schema) => {

@@ -426,2 +435,38 @@ return standardSchemaValidator.standardSchemaValidators.validate(

};
this.triggerOnChangeListener = () => {
const formDebounceMs = this.form.options.listeners?.onChangeDebounceMs;
if (formDebounceMs && formDebounceMs > 0) {
if (this.timeoutIds.formListeners.change) {
clearTimeout(this.timeoutIds.formListeners.change);
}
this.timeoutIds.formListeners.change = setTimeout(() => {
this.form.options.listeners?.onChange?.({
formApi: this.form,
fieldApi: this
});
}, formDebounceMs);
} else {
this.form.options.listeners?.onChange?.({
formApi: this.form,
fieldApi: this
});
}
const fieldDebounceMs = this.options.listeners?.onChangeDebounceMs;
if (fieldDebounceMs && fieldDebounceMs > 0) {
if (this.timeoutIds.listeners.change) {
clearTimeout(this.timeoutIds.listeners.change);
}
this.timeoutIds.listeners.change = setTimeout(() => {
this.options.listeners?.onChange?.({
value: this.state.value,
fieldApi: this
});
}, fieldDebounceMs);
} else {
this.options.listeners?.onChange?.({
value: this.state.value,
fieldApi: this
});
}
};
this.form = opts.form;

@@ -471,14 +516,2 @@ this.name = opts.name;

}
/**
* Updates the field's errorMap
*/
setErrorMap(errorMap) {
this.setMeta((prev) => ({
...prev,
errorMap: {
...prev.errorMap,
...errorMap
}
}));
}
triggerOnBlurListener() {

@@ -520,41 +553,2 @@ const formDebounceMs = this.form.options.listeners?.onBlurDebounceMs;

}
/**
* @private
*/
triggerOnChangeListener() {
const formDebounceMs = this.form.options.listeners?.onChangeDebounceMs;
if (formDebounceMs && formDebounceMs > 0) {
if (this.timeoutIds.formListeners.change) {
clearTimeout(this.timeoutIds.formListeners.change);
}
this.timeoutIds.formListeners.change = setTimeout(() => {
this.form.options.listeners?.onChange?.({
formApi: this.form,
fieldApi: this
});
}, formDebounceMs);
} else {
this.form.options.listeners?.onChange?.({
formApi: this.form,
fieldApi: this
});
}
const fieldDebounceMs = this.options.listeners?.onChangeDebounceMs;
if (fieldDebounceMs && fieldDebounceMs > 0) {
if (this.timeoutIds.listeners.change) {
clearTimeout(this.timeoutIds.listeners.change);
}
this.timeoutIds.listeners.change = setTimeout(() => {
this.options.listeners?.onChange?.({
value: this.state.value,
fieldApi: this
});
}, fieldDebounceMs);
} else {
this.options.listeners?.onChange?.({
value: this.state.value,
fieldApi: this
});
}
}
}

@@ -561,0 +555,0 @@ function normalizeError(rawError) {

@@ -243,2 +243,6 @@ import { Derived } from '@tanstack/store';

/**
* We cannot use methods and must use arrow functions. Otherwise, our React adapters
* will break due to loss of the method when using spread.
*/
/**
* A class representing the API for managing a form field.

@@ -377,3 +381,3 @@ *

*/
setErrorMap(errorMap: ValidationErrorMap<UnwrapFieldValidateOrFn<TName, TOnMount, TFormOnMount>, UnwrapFieldValidateOrFn<TName, TOnChange, TFormOnChange>, UnwrapFieldAsyncValidateOrFn<TName, TOnChangeAsync, TFormOnChangeAsync>, UnwrapFieldValidateOrFn<TName, TOnBlur, TFormOnBlur>, UnwrapFieldAsyncValidateOrFn<TName, TOnBlurAsync, TFormOnBlurAsync>, UnwrapFieldValidateOrFn<TName, TOnSubmit, TFormOnSubmit>, UnwrapFieldAsyncValidateOrFn<TName, TOnSubmitAsync, TFormOnSubmitAsync>, UnwrapFieldValidateOrFn<TName, TOnDynamic, TFormOnDynamic>, UnwrapFieldAsyncValidateOrFn<TName, TOnDynamicAsync, TFormOnDynamicAsync>>): void;
setErrorMap: (errorMap: ValidationErrorMap<UnwrapFieldValidateOrFn<TName, TOnMount, TFormOnMount>, UnwrapFieldValidateOrFn<TName, TOnChange, TFormOnChange>, UnwrapFieldAsyncValidateOrFn<TName, TOnChangeAsync, TFormOnChangeAsync>, UnwrapFieldValidateOrFn<TName, TOnBlur, TFormOnBlur>, UnwrapFieldAsyncValidateOrFn<TName, TOnBlurAsync, TFormOnBlurAsync>, UnwrapFieldValidateOrFn<TName, TOnSubmit, TFormOnSubmit>, UnwrapFieldAsyncValidateOrFn<TName, TOnSubmitAsync, TFormOnSubmitAsync>, UnwrapFieldValidateOrFn<TName, TOnDynamic, TFormOnDynamic>, UnwrapFieldAsyncValidateOrFn<TName, TOnDynamicAsync, TFormOnDynamicAsync>>) => void;
/**

@@ -395,4 +399,4 @@ * Parses the field's value with the given schema and returns

*/
triggerOnChangeListener(): void;
triggerOnChangeListener: () => void;
}
export {};

@@ -408,2 +408,117 @@ "use strict";

};
this._handleSubmit = async (submitMeta) => {
this.baseStore.setState((old) => ({
...old,
// Submission attempts mark the form as not submitted
isSubmitted: false,
// Count submission attempts
submissionAttempts: old.submissionAttempts + 1,
isSubmitSuccessful: false
// Reset isSubmitSuccessful at the start of submission
}));
store.batch(() => {
void Object.values(this.fieldInfo).forEach(
(field) => {
if (!field.instance) return;
if (!field.instance.state.meta.isTouched) {
field.instance.setMeta((prev) => ({ ...prev, isTouched: true }));
}
}
);
});
const submitMetaArg = submitMeta ?? this.options.onSubmitMeta;
if (!this.state.canSubmit && !this._devtoolsSubmissionOverride) {
this.options.onSubmitInvalid?.({
value: this.state.values,
formApi: this,
meta: submitMetaArg
});
return;
}
this.baseStore.setState((d) => ({ ...d, isSubmitting: true }));
const done = () => {
this.baseStore.setState((prev) => ({ ...prev, isSubmitting: false }));
};
await this.validateAllFields("submit");
if (!this.state.isFieldsValid) {
done();
this.options.onSubmitInvalid?.({
value: this.state.values,
formApi: this,
meta: submitMetaArg
});
EventClient.formEventClient.emit("form-submission", {
id: this._formId,
submissionAttempt: this.state.submissionAttempts,
successful: false,
stage: "validateAllFields",
errors: Object.values(this.state.fieldMeta).map((meta) => meta.errors).flat()
});
return;
}
await this.validate("submit");
if (!this.state.isValid) {
done();
this.options.onSubmitInvalid?.({
value: this.state.values,
formApi: this,
meta: submitMetaArg
});
EventClient.formEventClient.emit("form-submission", {
id: this._formId,
submissionAttempt: this.state.submissionAttempts,
successful: false,
stage: "validate",
errors: this.state.errors
});
return;
}
store.batch(() => {
void Object.values(this.fieldInfo).forEach(
(field) => {
field.instance?.options.listeners?.onSubmit?.({
value: field.instance.state.value,
fieldApi: field.instance
});
}
);
});
this.options.listeners?.onSubmit?.({ formApi: this, meta: submitMetaArg });
try {
await this.options.onSubmit?.({
value: this.state.values,
formApi: this,
meta: submitMetaArg
});
store.batch(() => {
this.baseStore.setState((prev) => ({
...prev,
isSubmitted: true,
isSubmitSuccessful: true
// Set isSubmitSuccessful to true on successful submission
}));
EventClient.formEventClient.emit("form-submission", {
id: this._formId,
submissionAttempt: this.state.submissionAttempts,
successful: true
});
done();
});
} catch (err) {
this.baseStore.setState((prev) => ({
...prev,
isSubmitSuccessful: false
// Ensure isSubmitSuccessful is false if an error occurs
}));
EventClient.formEventClient.emit("form-submission", {
id: this._formId,
submissionAttempt: this.state.submissionAttempts,
successful: false,
stage: "inflight",
onError: err
});
done();
throw err;
}
};
this.getFieldValue = (field) => utils.getBy(this.state.values, field);

@@ -631,2 +746,44 @@ this.getFieldMeta = (field) => {

};
this.setErrorMap = (errorMap) => {
store.batch(() => {
Object.entries(errorMap).forEach(([key, value]) => {
const errorMapKey = key;
if (utils.isGlobalFormValidationError(value)) {
const { formError, fieldErrors } = normalizeError(value);
for (const fieldName of Object.keys(
this.fieldInfo
)) {
const fieldMeta = this.getFieldMeta(fieldName);
if (!fieldMeta) continue;
this.setFieldMeta(fieldName, (prev) => ({
...prev,
errorMap: {
...prev.errorMap,
[errorMapKey]: fieldErrors?.[fieldName]
},
errorSourceMap: {
...prev.errorSourceMap,
[errorMapKey]: "form"
}
}));
}
this.baseStore.setState((prev) => ({
...prev,
errorMap: {
...prev.errorMap,
[errorMapKey]: formError
}
}));
} else {
this.baseStore.setState((prev) => ({
...prev,
errorMap: {
...prev.errorMap,
[errorMapKey]: value
}
}));
}
});
});
};
this.getAllErrors = () => {

@@ -870,162 +1027,5 @@ return {

}
async handleSubmit(submitMeta) {
this.baseStore.setState((old) => ({
...old,
// Submission attempts mark the form as not submitted
isSubmitted: false,
// Count submission attempts
submissionAttempts: old.submissionAttempts + 1,
isSubmitSuccessful: false
// Reset isSubmitSuccessful at the start of submission
}));
store.batch(() => {
void Object.values(this.fieldInfo).forEach(
(field) => {
if (!field.instance) return;
if (!field.instance.state.meta.isTouched) {
field.instance.setMeta((prev) => ({ ...prev, isTouched: true }));
}
}
);
});
const submitMetaArg = submitMeta ?? this.options.onSubmitMeta;
if (!this.state.canSubmit && !this._devtoolsSubmissionOverride) {
this.options.onSubmitInvalid?.({
value: this.state.values,
formApi: this,
meta: submitMetaArg
});
return;
}
this.baseStore.setState((d) => ({ ...d, isSubmitting: true }));
const done = () => {
this.baseStore.setState((prev) => ({ ...prev, isSubmitting: false }));
};
await this.validateAllFields("submit");
if (!this.state.isFieldsValid) {
done();
this.options.onSubmitInvalid?.({
value: this.state.values,
formApi: this,
meta: submitMetaArg
});
EventClient.formEventClient.emit("form-submission", {
id: this._formId,
submissionAttempt: this.state.submissionAttempts,
successful: false,
stage: "validateAllFields",
errors: Object.values(this.state.fieldMeta).map((meta) => meta.errors).flat()
});
return;
}
await this.validate("submit");
if (!this.state.isValid) {
done();
this.options.onSubmitInvalid?.({
value: this.state.values,
formApi: this,
meta: submitMetaArg
});
EventClient.formEventClient.emit("form-submission", {
id: this._formId,
submissionAttempt: this.state.submissionAttempts,
successful: false,
stage: "validate",
errors: this.state.errors
});
return;
}
store.batch(() => {
void Object.values(this.fieldInfo).forEach(
(field) => {
field.instance?.options.listeners?.onSubmit?.({
value: field.instance.state.value,
fieldApi: field.instance
});
}
);
});
this.options.listeners?.onSubmit?.({ formApi: this, meta: submitMetaArg });
try {
await this.options.onSubmit?.({
value: this.state.values,
formApi: this,
meta: submitMetaArg
});
store.batch(() => {
this.baseStore.setState((prev) => ({
...prev,
isSubmitted: true,
isSubmitSuccessful: true
// Set isSubmitSuccessful to true on successful submission
}));
EventClient.formEventClient.emit("form-submission", {
id: this._formId,
submissionAttempt: this.state.submissionAttempts,
successful: true
});
done();
});
} catch (err) {
this.baseStore.setState((prev) => ({
...prev,
isSubmitSuccessful: false
// Ensure isSubmitSuccessful is false if an error occurs
}));
EventClient.formEventClient.emit("form-submission", {
id: this._formId,
submissionAttempt: this.state.submissionAttempts,
successful: false,
stage: "inflight",
onError: err
});
done();
throw err;
}
handleSubmit(submitMeta) {
return this._handleSubmit(submitMeta);
}
/**
* Updates the form's errorMap
*/
setErrorMap(errorMap) {
store.batch(() => {
Object.entries(errorMap).forEach(([key, value]) => {
const errorMapKey = key;
if (utils.isGlobalFormValidationError(value)) {
const { formError, fieldErrors } = normalizeError(value);
for (const fieldName of Object.keys(
this.fieldInfo
)) {
const fieldMeta = this.getFieldMeta(fieldName);
if (!fieldMeta) continue;
this.setFieldMeta(fieldName, (prev) => ({
...prev,
errorMap: {
...prev.errorMap,
[errorMapKey]: fieldErrors?.[fieldName]
},
errorSourceMap: {
...prev.errorSourceMap,
[errorMapKey]: "form"
}
}));
}
this.baseStore.setState((prev) => ({
...prev,
errorMap: {
...prev.errorMap,
[errorMapKey]: formError
}
}));
} else {
this.baseStore.setState((prev) => ({
...prev,
errorMap: {
...prev.errorMap,
[errorMapKey]: value
}
}));
}
});
});
}
}

@@ -1032,0 +1032,0 @@ function normalizeError(rawError) {

@@ -312,2 +312,6 @@ import { Derived, Store } from '@tanstack/store';

/**
* We cannot use methods and must use arrow functions. Otherwise, our React adapters
* will break due to loss of the method when using spread.
*/
/**
* A class representing the Form API. It handles the logic and interactions with the form state.

@@ -410,7 +414,8 @@ *

validate: (cause: ValidationCause) => FormErrorMapFromValidator<TFormData, TOnMount, TOnChange, TOnChangeAsync, TOnBlur, TOnBlurAsync, TOnSubmit, TOnSubmitAsync, TOnDynamic, TOnDynamicAsync> | Promise<FormErrorMapFromValidator<TFormData, TOnMount, TOnChange, TOnChangeAsync, TOnBlur, TOnBlurAsync, TOnSubmit, TOnSubmitAsync, TOnDynamic, TOnDynamicAsync>>;
handleSubmit(): Promise<void>;
handleSubmit(submitMeta: TSubmitMeta): Promise<void>;
/**
* Handles the form submission, performs validation, and calls the appropriate onSubmit or onSubmitInvalid callbacks.
*/
handleSubmit(): Promise<void>;
handleSubmit(submitMeta: TSubmitMeta): Promise<void>;
_handleSubmit: (submitMeta?: TSubmitMeta) => Promise<void>;
/**

@@ -473,3 +478,3 @@ * Gets the value of the specified field.

*/
setErrorMap(errorMap: FormValidationErrorMap<TFormData, UnwrapFormValidateOrFn<TOnMount>, UnwrapFormValidateOrFn<TOnChange>, UnwrapFormAsyncValidateOrFn<TOnChangeAsync>, UnwrapFormValidateOrFn<TOnBlur>, UnwrapFormAsyncValidateOrFn<TOnBlurAsync>, UnwrapFormValidateOrFn<TOnSubmit>, UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>, UnwrapFormValidateOrFn<TOnDynamic>, UnwrapFormAsyncValidateOrFn<TOnDynamicAsync>, UnwrapFormAsyncValidateOrFn<TOnServer>>): void;
setErrorMap: (errorMap: FormValidationErrorMap<TFormData, UnwrapFormValidateOrFn<TOnMount>, UnwrapFormValidateOrFn<TOnChange>, UnwrapFormAsyncValidateOrFn<TOnChangeAsync>, UnwrapFormValidateOrFn<TOnBlur>, UnwrapFormAsyncValidateOrFn<TOnBlurAsync>, UnwrapFormValidateOrFn<TOnSubmit>, UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>, UnwrapFormValidateOrFn<TOnDynamic>, UnwrapFormAsyncValidateOrFn<TOnDynamicAsync>, UnwrapFormAsyncValidateOrFn<TOnServer>>) => void;
/**

@@ -476,0 +481,0 @@ * Returns form and field level errors

@@ -243,2 +243,6 @@ import { Derived } from '@tanstack/store';

/**
* We cannot use methods and must use arrow functions. Otherwise, our React adapters
* will break due to loss of the method when using spread.
*/
/**
* A class representing the API for managing a form field.

@@ -377,3 +381,3 @@ *

*/
setErrorMap(errorMap: ValidationErrorMap<UnwrapFieldValidateOrFn<TName, TOnMount, TFormOnMount>, UnwrapFieldValidateOrFn<TName, TOnChange, TFormOnChange>, UnwrapFieldAsyncValidateOrFn<TName, TOnChangeAsync, TFormOnChangeAsync>, UnwrapFieldValidateOrFn<TName, TOnBlur, TFormOnBlur>, UnwrapFieldAsyncValidateOrFn<TName, TOnBlurAsync, TFormOnBlurAsync>, UnwrapFieldValidateOrFn<TName, TOnSubmit, TFormOnSubmit>, UnwrapFieldAsyncValidateOrFn<TName, TOnSubmitAsync, TFormOnSubmitAsync>, UnwrapFieldValidateOrFn<TName, TOnDynamic, TFormOnDynamic>, UnwrapFieldAsyncValidateOrFn<TName, TOnDynamicAsync, TFormOnDynamicAsync>>): void;
setErrorMap: (errorMap: ValidationErrorMap<UnwrapFieldValidateOrFn<TName, TOnMount, TFormOnMount>, UnwrapFieldValidateOrFn<TName, TOnChange, TFormOnChange>, UnwrapFieldAsyncValidateOrFn<TName, TOnChangeAsync, TFormOnChangeAsync>, UnwrapFieldValidateOrFn<TName, TOnBlur, TFormOnBlur>, UnwrapFieldAsyncValidateOrFn<TName, TOnBlurAsync, TFormOnBlurAsync>, UnwrapFieldValidateOrFn<TName, TOnSubmit, TFormOnSubmit>, UnwrapFieldAsyncValidateOrFn<TName, TOnSubmitAsync, TFormOnSubmitAsync>, UnwrapFieldValidateOrFn<TName, TOnDynamic, TFormOnDynamic>, UnwrapFieldAsyncValidateOrFn<TName, TOnDynamicAsync, TFormOnDynamicAsync>>) => void;
/**

@@ -395,4 +399,4 @@ * Parses the field's value with the given schema and returns

*/
triggerOnChangeListener(): void;
triggerOnChangeListener: () => void;
}
export {};

@@ -411,2 +411,11 @@ import { batch, Derived } from "@tanstack/store";

};
this.setErrorMap = (errorMap) => {
this.setMeta((prev) => ({
...prev,
errorMap: {
...prev.errorMap,
...errorMap
}
}));
};
this.parseValueWithSchema = (schema) => {

@@ -424,2 +433,38 @@ return standardSchemaValidators.validate(

};
this.triggerOnChangeListener = () => {
const formDebounceMs = this.form.options.listeners?.onChangeDebounceMs;
if (formDebounceMs && formDebounceMs > 0) {
if (this.timeoutIds.formListeners.change) {
clearTimeout(this.timeoutIds.formListeners.change);
}
this.timeoutIds.formListeners.change = setTimeout(() => {
this.form.options.listeners?.onChange?.({
formApi: this.form,
fieldApi: this
});
}, formDebounceMs);
} else {
this.form.options.listeners?.onChange?.({
formApi: this.form,
fieldApi: this
});
}
const fieldDebounceMs = this.options.listeners?.onChangeDebounceMs;
if (fieldDebounceMs && fieldDebounceMs > 0) {
if (this.timeoutIds.listeners.change) {
clearTimeout(this.timeoutIds.listeners.change);
}
this.timeoutIds.listeners.change = setTimeout(() => {
this.options.listeners?.onChange?.({
value: this.state.value,
fieldApi: this
});
}, fieldDebounceMs);
} else {
this.options.listeners?.onChange?.({
value: this.state.value,
fieldApi: this
});
}
};
this.form = opts.form;

@@ -469,14 +514,2 @@ this.name = opts.name;

}
/**
* Updates the field's errorMap
*/
setErrorMap(errorMap) {
this.setMeta((prev) => ({
...prev,
errorMap: {
...prev.errorMap,
...errorMap
}
}));
}
triggerOnBlurListener() {

@@ -518,41 +551,2 @@ const formDebounceMs = this.form.options.listeners?.onBlurDebounceMs;

}
/**
* @private
*/
triggerOnChangeListener() {
const formDebounceMs = this.form.options.listeners?.onChangeDebounceMs;
if (formDebounceMs && formDebounceMs > 0) {
if (this.timeoutIds.formListeners.change) {
clearTimeout(this.timeoutIds.formListeners.change);
}
this.timeoutIds.formListeners.change = setTimeout(() => {
this.form.options.listeners?.onChange?.({
formApi: this.form,
fieldApi: this
});
}, formDebounceMs);
} else {
this.form.options.listeners?.onChange?.({
formApi: this.form,
fieldApi: this
});
}
const fieldDebounceMs = this.options.listeners?.onChangeDebounceMs;
if (fieldDebounceMs && fieldDebounceMs > 0) {
if (this.timeoutIds.listeners.change) {
clearTimeout(this.timeoutIds.listeners.change);
}
this.timeoutIds.listeners.change = setTimeout(() => {
this.options.listeners?.onChange?.({
value: this.state.value,
fieldApi: this
});
}, fieldDebounceMs);
} else {
this.options.listeners?.onChange?.({
value: this.state.value,
fieldApi: this
});
}
}
}

@@ -559,0 +553,0 @@ function normalizeError(rawError) {

@@ -312,2 +312,6 @@ import { Derived, Store } from '@tanstack/store';

/**
* We cannot use methods and must use arrow functions. Otherwise, our React adapters
* will break due to loss of the method when using spread.
*/
/**
* A class representing the Form API. It handles the logic and interactions with the form state.

@@ -410,7 +414,8 @@ *

validate: (cause: ValidationCause) => FormErrorMapFromValidator<TFormData, TOnMount, TOnChange, TOnChangeAsync, TOnBlur, TOnBlurAsync, TOnSubmit, TOnSubmitAsync, TOnDynamic, TOnDynamicAsync> | Promise<FormErrorMapFromValidator<TFormData, TOnMount, TOnChange, TOnChangeAsync, TOnBlur, TOnBlurAsync, TOnSubmit, TOnSubmitAsync, TOnDynamic, TOnDynamicAsync>>;
handleSubmit(): Promise<void>;
handleSubmit(submitMeta: TSubmitMeta): Promise<void>;
/**
* Handles the form submission, performs validation, and calls the appropriate onSubmit or onSubmitInvalid callbacks.
*/
handleSubmit(): Promise<void>;
handleSubmit(submitMeta: TSubmitMeta): Promise<void>;
_handleSubmit: (submitMeta?: TSubmitMeta) => Promise<void>;
/**

@@ -473,3 +478,3 @@ * Gets the value of the specified field.

*/
setErrorMap(errorMap: FormValidationErrorMap<TFormData, UnwrapFormValidateOrFn<TOnMount>, UnwrapFormValidateOrFn<TOnChange>, UnwrapFormAsyncValidateOrFn<TOnChangeAsync>, UnwrapFormValidateOrFn<TOnBlur>, UnwrapFormAsyncValidateOrFn<TOnBlurAsync>, UnwrapFormValidateOrFn<TOnSubmit>, UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>, UnwrapFormValidateOrFn<TOnDynamic>, UnwrapFormAsyncValidateOrFn<TOnDynamicAsync>, UnwrapFormAsyncValidateOrFn<TOnServer>>): void;
setErrorMap: (errorMap: FormValidationErrorMap<TFormData, UnwrapFormValidateOrFn<TOnMount>, UnwrapFormValidateOrFn<TOnChange>, UnwrapFormAsyncValidateOrFn<TOnChangeAsync>, UnwrapFormValidateOrFn<TOnBlur>, UnwrapFormAsyncValidateOrFn<TOnBlurAsync>, UnwrapFormValidateOrFn<TOnSubmit>, UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>, UnwrapFormValidateOrFn<TOnDynamic>, UnwrapFormAsyncValidateOrFn<TOnDynamicAsync>, UnwrapFormAsyncValidateOrFn<TOnServer>>) => void;
/**

@@ -476,0 +481,0 @@ * Returns form and field level errors

import { batch, Store, Derived } from "@tanstack/store";
import { throttle } from "@tanstack/pacer";
import { evaluate, getSyncValidatorArray, determineFormLevelErrorSourceAndValue, getAsyncValidatorArray, getBy, functionalUpdate, setBy, deleteBy, mergeOpts, uuid, isNonEmptyArray, isGlobalFormValidationError } from "./utils.js";
import { evaluate, getSyncValidatorArray, determineFormLevelErrorSourceAndValue, getAsyncValidatorArray, getBy, functionalUpdate, setBy, deleteBy, mergeOpts, isGlobalFormValidationError, uuid, isNonEmptyArray } from "./utils.js";
import { defaultValidationLogic } from "./ValidationLogic.js";

@@ -406,2 +406,117 @@ import { standardSchemaValidators, isStandardSchemaValidator } from "./standardSchemaValidator.js";

};
this._handleSubmit = async (submitMeta) => {
this.baseStore.setState((old) => ({
...old,
// Submission attempts mark the form as not submitted
isSubmitted: false,
// Count submission attempts
submissionAttempts: old.submissionAttempts + 1,
isSubmitSuccessful: false
// Reset isSubmitSuccessful at the start of submission
}));
batch(() => {
void Object.values(this.fieldInfo).forEach(
(field) => {
if (!field.instance) return;
if (!field.instance.state.meta.isTouched) {
field.instance.setMeta((prev) => ({ ...prev, isTouched: true }));
}
}
);
});
const submitMetaArg = submitMeta ?? this.options.onSubmitMeta;
if (!this.state.canSubmit && !this._devtoolsSubmissionOverride) {
this.options.onSubmitInvalid?.({
value: this.state.values,
formApi: this,
meta: submitMetaArg
});
return;
}
this.baseStore.setState((d) => ({ ...d, isSubmitting: true }));
const done = () => {
this.baseStore.setState((prev) => ({ ...prev, isSubmitting: false }));
};
await this.validateAllFields("submit");
if (!this.state.isFieldsValid) {
done();
this.options.onSubmitInvalid?.({
value: this.state.values,
formApi: this,
meta: submitMetaArg
});
formEventClient.emit("form-submission", {
id: this._formId,
submissionAttempt: this.state.submissionAttempts,
successful: false,
stage: "validateAllFields",
errors: Object.values(this.state.fieldMeta).map((meta) => meta.errors).flat()
});
return;
}
await this.validate("submit");
if (!this.state.isValid) {
done();
this.options.onSubmitInvalid?.({
value: this.state.values,
formApi: this,
meta: submitMetaArg
});
formEventClient.emit("form-submission", {
id: this._formId,
submissionAttempt: this.state.submissionAttempts,
successful: false,
stage: "validate",
errors: this.state.errors
});
return;
}
batch(() => {
void Object.values(this.fieldInfo).forEach(
(field) => {
field.instance?.options.listeners?.onSubmit?.({
value: field.instance.state.value,
fieldApi: field.instance
});
}
);
});
this.options.listeners?.onSubmit?.({ formApi: this, meta: submitMetaArg });
try {
await this.options.onSubmit?.({
value: this.state.values,
formApi: this,
meta: submitMetaArg
});
batch(() => {
this.baseStore.setState((prev) => ({
...prev,
isSubmitted: true,
isSubmitSuccessful: true
// Set isSubmitSuccessful to true on successful submission
}));
formEventClient.emit("form-submission", {
id: this._formId,
submissionAttempt: this.state.submissionAttempts,
successful: true
});
done();
});
} catch (err) {
this.baseStore.setState((prev) => ({
...prev,
isSubmitSuccessful: false
// Ensure isSubmitSuccessful is false if an error occurs
}));
formEventClient.emit("form-submission", {
id: this._formId,
submissionAttempt: this.state.submissionAttempts,
successful: false,
stage: "inflight",
onError: err
});
done();
throw err;
}
};
this.getFieldValue = (field) => getBy(this.state.values, field);

@@ -629,2 +744,44 @@ this.getFieldMeta = (field) => {

};
this.setErrorMap = (errorMap) => {
batch(() => {
Object.entries(errorMap).forEach(([key, value]) => {
const errorMapKey = key;
if (isGlobalFormValidationError(value)) {
const { formError, fieldErrors } = normalizeError(value);
for (const fieldName of Object.keys(
this.fieldInfo
)) {
const fieldMeta = this.getFieldMeta(fieldName);
if (!fieldMeta) continue;
this.setFieldMeta(fieldName, (prev) => ({
...prev,
errorMap: {
...prev.errorMap,
[errorMapKey]: fieldErrors?.[fieldName]
},
errorSourceMap: {
...prev.errorSourceMap,
[errorMapKey]: "form"
}
}));
}
this.baseStore.setState((prev) => ({
...prev,
errorMap: {
...prev.errorMap,
[errorMapKey]: formError
}
}));
} else {
this.baseStore.setState((prev) => ({
...prev,
errorMap: {
...prev.errorMap,
[errorMapKey]: value
}
}));
}
});
});
};
this.getAllErrors = () => {

@@ -868,162 +1025,5 @@ return {

}
async handleSubmit(submitMeta) {
this.baseStore.setState((old) => ({
...old,
// Submission attempts mark the form as not submitted
isSubmitted: false,
// Count submission attempts
submissionAttempts: old.submissionAttempts + 1,
isSubmitSuccessful: false
// Reset isSubmitSuccessful at the start of submission
}));
batch(() => {
void Object.values(this.fieldInfo).forEach(
(field) => {
if (!field.instance) return;
if (!field.instance.state.meta.isTouched) {
field.instance.setMeta((prev) => ({ ...prev, isTouched: true }));
}
}
);
});
const submitMetaArg = submitMeta ?? this.options.onSubmitMeta;
if (!this.state.canSubmit && !this._devtoolsSubmissionOverride) {
this.options.onSubmitInvalid?.({
value: this.state.values,
formApi: this,
meta: submitMetaArg
});
return;
}
this.baseStore.setState((d) => ({ ...d, isSubmitting: true }));
const done = () => {
this.baseStore.setState((prev) => ({ ...prev, isSubmitting: false }));
};
await this.validateAllFields("submit");
if (!this.state.isFieldsValid) {
done();
this.options.onSubmitInvalid?.({
value: this.state.values,
formApi: this,
meta: submitMetaArg
});
formEventClient.emit("form-submission", {
id: this._formId,
submissionAttempt: this.state.submissionAttempts,
successful: false,
stage: "validateAllFields",
errors: Object.values(this.state.fieldMeta).map((meta) => meta.errors).flat()
});
return;
}
await this.validate("submit");
if (!this.state.isValid) {
done();
this.options.onSubmitInvalid?.({
value: this.state.values,
formApi: this,
meta: submitMetaArg
});
formEventClient.emit("form-submission", {
id: this._formId,
submissionAttempt: this.state.submissionAttempts,
successful: false,
stage: "validate",
errors: this.state.errors
});
return;
}
batch(() => {
void Object.values(this.fieldInfo).forEach(
(field) => {
field.instance?.options.listeners?.onSubmit?.({
value: field.instance.state.value,
fieldApi: field.instance
});
}
);
});
this.options.listeners?.onSubmit?.({ formApi: this, meta: submitMetaArg });
try {
await this.options.onSubmit?.({
value: this.state.values,
formApi: this,
meta: submitMetaArg
});
batch(() => {
this.baseStore.setState((prev) => ({
...prev,
isSubmitted: true,
isSubmitSuccessful: true
// Set isSubmitSuccessful to true on successful submission
}));
formEventClient.emit("form-submission", {
id: this._formId,
submissionAttempt: this.state.submissionAttempts,
successful: true
});
done();
});
} catch (err) {
this.baseStore.setState((prev) => ({
...prev,
isSubmitSuccessful: false
// Ensure isSubmitSuccessful is false if an error occurs
}));
formEventClient.emit("form-submission", {
id: this._formId,
submissionAttempt: this.state.submissionAttempts,
successful: false,
stage: "inflight",
onError: err
});
done();
throw err;
}
handleSubmit(submitMeta) {
return this._handleSubmit(submitMeta);
}
/**
* Updates the form's errorMap
*/
setErrorMap(errorMap) {
batch(() => {
Object.entries(errorMap).forEach(([key, value]) => {
const errorMapKey = key;
if (isGlobalFormValidationError(value)) {
const { formError, fieldErrors } = normalizeError(value);
for (const fieldName of Object.keys(
this.fieldInfo
)) {
const fieldMeta = this.getFieldMeta(fieldName);
if (!fieldMeta) continue;
this.setFieldMeta(fieldName, (prev) => ({
...prev,
errorMap: {
...prev.errorMap,
[errorMapKey]: fieldErrors?.[fieldName]
},
errorSourceMap: {
...prev.errorSourceMap,
[errorMapKey]: "form"
}
}));
}
this.baseStore.setState((prev) => ({
...prev,
errorMap: {
...prev.errorMap,
[errorMapKey]: formError
}
}));
} else {
this.baseStore.setState((prev) => ({
...prev,
errorMap: {
...prev.errorMap,
[errorMapKey]: value
}
}));
}
});
});
}
}

@@ -1030,0 +1030,0 @@ function normalizeError(rawError) {

{
"name": "@tanstack/form-core",
"version": "1.27.0",
"version": "1.27.1",
"description": "Powerful, type-safe, framework agnostic forms.",

@@ -5,0 +5,0 @@ "author": "tannerlinsley",

@@ -966,2 +966,7 @@ import { Derived, batch } from '@tanstack/store'

/**
* We cannot use methods and must use arrow functions. Otherwise, our React adapters
* will break due to loss of the method when using spread.
*/
/**
* A class representing the API for managing a form field.

@@ -1912,3 +1917,3 @@ *

*/
setErrorMap(
setErrorMap = (
errorMap: ValidationErrorMap<

@@ -1925,3 +1930,3 @@ UnwrapFieldValidateOrFn<TName, TOnMount, TFormOnMount>,

>,
) {
) => {
this.setMeta((prev) => ({

@@ -2003,3 +2008,3 @@ ...prev,

*/
triggerOnChangeListener() {
triggerOnChangeListener = () => {
const formDebounceMs = this.form.options.listeners?.onChangeDebounceMs

@@ -2006,0 +2011,0 @@ if (formDebounceMs && formDebounceMs > 0) {

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display