@tanstack/form-core 1.26.0 → 1.27.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -405,6 +405,121 @@ class FormApi {
405
405
  }
406
406
  return this.validateAsync(cause);
407
407
  };
408
+ this._handleSubmit = async (submitMeta) => {
409
+ this.baseStore.setState((old) => ({
410
+ ...old,
411
+ // Submission attempts mark the form as not submitted
412
+ isSubmitted: false,
413
+ // Count submission attempts
414
+ submissionAttempts: old.submissionAttempts + 1,
415
+ isSubmitSuccessful: false
416
+ // Reset isSubmitSuccessful at the start of submission
417
+ }));
418
+ store.batch(() => {
419
+ void Object.values(this.fieldInfo).forEach(
420
+ (field) => {
421
+ if (!field.instance) return;
422
+ if (!field.instance.state.meta.isTouched) {
423
+ field.instance.setMeta((prev) => ({ ...prev, isTouched: true }));
424
+ }
425
+ }
426
+ );
427
+ });
428
+ const submitMetaArg = submitMeta ?? this.options.onSubmitMeta;
429
+ if (!this.state.canSubmit && !this._devtoolsSubmissionOverride) {
430
+ this.options.onSubmitInvalid?.({
431
+ value: this.state.values,
432
+ formApi: this,
433
+ meta: submitMetaArg
434
+ });
435
+ return;
436
+ }
437
+ this.baseStore.setState((d) => ({ ...d, isSubmitting: true }));
438
+ const done = () => {
439
+ this.baseStore.setState((prev) => ({ ...prev, isSubmitting: false }));
440
+ };
441
+ await this.validateAllFields("submit");
442
+ if (!this.state.isFieldsValid) {
443
+ done();
444
+ this.options.onSubmitInvalid?.({
445
+ value: this.state.values,
446
+ formApi: this,
447
+ meta: submitMetaArg
448
+ });
449
+ EventClient.formEventClient.emit("form-submission", {
450
+ id: this._formId,
451
+ submissionAttempt: this.state.submissionAttempts,
452
+ successful: false,
453
+ stage: "validateAllFields",
454
+ errors: Object.values(this.state.fieldMeta).map((meta) => meta.errors).flat()
455
+ });
456
+ return;
457
+ }
458
+ await this.validate("submit");
459
+ if (!this.state.isValid) {
460
+ done();
461
+ this.options.onSubmitInvalid?.({
462
+ value: this.state.values,
463
+ formApi: this,
464
+ meta: submitMetaArg
465
+ });
466
+ EventClient.formEventClient.emit("form-submission", {
467
+ id: this._formId,
468
+ submissionAttempt: this.state.submissionAttempts,
469
+ successful: false,
470
+ stage: "validate",
471
+ errors: this.state.errors
472
+ });
473
+ return;
474
+ }
475
+ store.batch(() => {
476
+ void Object.values(this.fieldInfo).forEach(
477
+ (field) => {
478
+ field.instance?.options.listeners?.onSubmit?.({
479
+ value: field.instance.state.value,
480
+ fieldApi: field.instance
481
+ });
482
+ }
483
+ );
484
+ });
485
+ this.options.listeners?.onSubmit?.({ formApi: this, meta: submitMetaArg });
486
+ try {
487
+ await this.options.onSubmit?.({
488
+ value: this.state.values,
489
+ formApi: this,
490
+ meta: submitMetaArg
491
+ });
492
+ store.batch(() => {
493
+ this.baseStore.setState((prev) => ({
494
+ ...prev,
495
+ isSubmitted: true,
496
+ isSubmitSuccessful: true
497
+ // Set isSubmitSuccessful to true on successful submission
498
+ }));
499
+ EventClient.formEventClient.emit("form-submission", {
500
+ id: this._formId,
501
+ submissionAttempt: this.state.submissionAttempts,
502
+ successful: true
503
+ });
504
+ done();
505
+ });
506
+ } catch (err) {
507
+ this.baseStore.setState((prev) => ({
508
+ ...prev,
509
+ isSubmitSuccessful: false
510
+ // Ensure isSubmitSuccessful is false if an error occurs
511
+ }));
512
+ EventClient.formEventClient.emit("form-submission", {
513
+ id: this._formId,
514
+ submissionAttempt: this.state.submissionAttempts,
515
+ successful: false,
516
+ stage: "inflight",
517
+ onError: err
518
+ });
519
+ done();
520
+ throw err;
521
+ }
522
+ };
408
523
  this.getFieldValue = (field) => utils.getBy(this.state.values, field);
409
524
  this.getFieldMeta = (field) => {
410
525
  return this.state.fieldMeta[field];
@@ -627,6 +742,48 @@ class FormApi {
627
742
  };
628
743
  });
629
744
  };
745
+ this.setErrorMap = (errorMap) => {
746
+ store.batch(() => {
747
+ Object.entries(errorMap).forEach(([key, value]) => {
748
+ const errorMapKey = key;
749
+ if (utils.isGlobalFormValidationError(value)) {
750
+ const { formError, fieldErrors } = normalizeError(value);
751
+ for (const fieldName of Object.keys(
752
+ this.fieldInfo
753
+ )) {
754
+ const fieldMeta = this.getFieldMeta(fieldName);
755
+ if (!fieldMeta) continue;
756
+ this.setFieldMeta(fieldName, (prev) => ({
757
+ ...prev,
758
+ errorMap: {
759
+ ...prev.errorMap,
760
+ [errorMapKey]: fieldErrors?.[fieldName]
761
+ },
762
+ errorSourceMap: {
763
+ ...prev.errorSourceMap,
764
+ [errorMapKey]: "form"
765
+ }
766
+ }));
767
+ }
768
+ this.baseStore.setState((prev) => ({
769
+ ...prev,
770
+ errorMap: {
771
+ ...prev.errorMap,
772
+ [errorMapKey]: formError
773
+ }
774
+ }));
775
+ } else {
776
+ this.baseStore.setState((prev) => ({
777
+ ...prev,
778
+ errorMap: {
779
+ ...prev.errorMap,
780
+ [errorMapKey]: value
781
+ }
782
+ }));
783
+ }
784
+ });
785
+ });
786
+ };
630
787
  this.getAllErrors = () => {
631
788
  return {
632
789
  form: {
@@ -865,165 +1022,8 @@ class FormApi {
865
1022
  }
866
1023
  return props.validate(props.value);
867
1024
  }
868
- async handleSubmit(submitMeta) {
869
- this.baseStore.setState((old) => ({
870
- ...old,
871
- // Submission attempts mark the form as not submitted
872
- isSubmitted: false,
873
- // Count submission attempts
874
- submissionAttempts: old.submissionAttempts + 1,
875
- isSubmitSuccessful: false
876
- // Reset isSubmitSuccessful at the start of submission
877
- }));
878
- store.batch(() => {
879
- void Object.values(this.fieldInfo).forEach(
880
- (field) => {
881
- if (!field.instance) return;
882
- if (!field.instance.state.meta.isTouched) {
883
- field.instance.setMeta((prev) => ({ ...prev, isTouched: true }));
884
- }
885
- }
886
- );
887
- });
888
- const submitMetaArg = submitMeta ?? this.options.onSubmitMeta;
889
- if (!this.state.canSubmit && !this._devtoolsSubmissionOverride) {
890
- this.options.onSubmitInvalid?.({
891
- value: this.state.values,
892
- formApi: this,
893
- meta: submitMetaArg
894
- });
895
- return;
896
- }
897
- this.baseStore.setState((d) => ({ ...d, isSubmitting: true }));
898
- const done = () => {
899
- this.baseStore.setState((prev) => ({ ...prev, isSubmitting: false }));
900
- };
901
- await this.validateAllFields("submit");
902
- if (!this.state.isFieldsValid) {
903
- done();
904
- this.options.onSubmitInvalid?.({
905
- value: this.state.values,
906
- formApi: this,
907
- meta: submitMetaArg
908
- });
909
- EventClient.formEventClient.emit("form-submission", {
910
- id: this._formId,
911
- submissionAttempt: this.state.submissionAttempts,
912
- successful: false,
913
- stage: "validateAllFields",
914
- errors: Object.values(this.state.fieldMeta).map((meta) => meta.errors).flat()
915
- });
916
- return;
917
- }
918
- await this.validate("submit");
919
- if (!this.state.isValid) {
920
- done();
921
- this.options.onSubmitInvalid?.({
922
- value: this.state.values,
923
- formApi: this,
924
- meta: submitMetaArg
925
- });
926
- EventClient.formEventClient.emit("form-submission", {
927
- id: this._formId,
928
- submissionAttempt: this.state.submissionAttempts,
929
- successful: false,
930
- stage: "validate",
931
- errors: this.state.errors
932
- });
933
- return;
934
- }
935
- store.batch(() => {
936
- void Object.values(this.fieldInfo).forEach(
937
- (field) => {
938
- field.instance?.options.listeners?.onSubmit?.({
939
- value: field.instance.state.value,
940
- fieldApi: field.instance
941
- });
942
- }
943
- );
944
- });
945
- this.options.listeners?.onSubmit?.({ formApi: this, meta: submitMetaArg });
946
- try {
947
- await this.options.onSubmit?.({
948
- value: this.state.values,
949
- formApi: this,
950
- meta: submitMetaArg
951
- });
952
- store.batch(() => {
953
- this.baseStore.setState((prev) => ({
954
- ...prev,
955
- isSubmitted: true,
956
- isSubmitSuccessful: true
957
- // Set isSubmitSuccessful to true on successful submission
958
- }));
959
- EventClient.formEventClient.emit("form-submission", {
960
- id: this._formId,
961
- submissionAttempt: this.state.submissionAttempts,
962
- successful: true
963
- });
964
- done();
965
- });
966
- } catch (err) {
967
- this.baseStore.setState((prev) => ({
968
- ...prev,
969
- isSubmitSuccessful: false
970
- // Ensure isSubmitSuccessful is false if an error occurs
971
- }));
972
- EventClient.formEventClient.emit("form-submission", {
973
- id: this._formId,
974
- submissionAttempt: this.state.submissionAttempts,
975
- successful: false,
976
- stage: "inflight",
977
- onError: err
978
- });
979
- done();
980
- throw err;
981
- }
982
- }
983
- /**
984
- * Updates the form's errorMap
985
- */
986
- setErrorMap(errorMap) {
987
- store.batch(() => {
988
- Object.entries(errorMap).forEach(([key, value]) => {
989
- const errorMapKey = key;
990
- if (utils.isGlobalFormValidationError(value)) {
991
- const { formError, fieldErrors } = normalizeError(value);
992
- for (const fieldName of Object.keys(
993
- this.fieldInfo
994
- )) {
995
- const fieldMeta = this.getFieldMeta(fieldName);
996
- if (!fieldMeta) continue;
997
- this.setFieldMeta(fieldName, (prev) => ({
998
- ...prev,
999
- errorMap: {
1000
- ...prev.errorMap,
1001
- [errorMapKey]: fieldErrors?.[fieldName]
1002
- },
1003
- errorSourceMap: {
1004
- ...prev.errorSourceMap,
1005
- [errorMapKey]: "form"
1006
- }
1007
- }));
1008
- }
1009
- this.baseStore.setState((prev) => ({
1010
- ...prev,
1011
- errorMap: {
1012
- ...prev.errorMap,
1013
- [errorMapKey]: formError
1014
- }
1015
- }));
1016
- } else {
1017
- this.baseStore.setState((prev) => ({
1018
- ...prev,
1019
- errorMap: {
1020
- ...prev.errorMap,
1021
- [errorMapKey]: value
1022
- }
1023
- }));
1024
- }
1025
- });
1026
- });
1025
+ handleSubmit(submitMeta) {
1026
+ return this._handleSubmit(submitMeta);
1027
1027
  }
1028
1028
  }
1029
1029
  function normalizeError(rawError) {