@reactables/forms 0.4.6-alpha.0 → 0.5.0-alpha.0

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.
@@ -22,6 +22,7 @@ interface AsyncFields {
22
22
  interface ValidatedFields {
23
23
  valid: boolean;
24
24
  errors: FormErrors;
25
+ childrenValid: boolean;
25
26
  }
26
27
  export interface Hub2Fields extends AsyncFields, ValidatedFields {
27
28
  }
@@ -9,6 +9,10 @@ export interface AddControl {
9
9
  config: AbstractControlConfig;
10
10
  controlRef: ControlRef;
11
11
  }
12
+ export interface PushControl {
13
+ config: AbstractControlConfig;
14
+ controlRef: ControlRef;
15
+ }
12
16
  export interface ControlAsyncValidationResponse {
13
17
  key: string;
14
18
  validatorIndex: number;
@@ -0,0 +1,4 @@
1
+ import { Action } from '@reactables/core';
2
+ import { BaseFormState } from '../../Models/Controls';
3
+ import { AddControl } from '../../Models/Payloads';
4
+ export declare const pushControl: <T>(state: BaseFormState<T>, action: Action<AddControl>) => BaseFormState<T>;
@@ -0,0 +1,5 @@
1
+ import { Form, BaseForm } from '../../Models/Controls';
2
+ import { ControlRef } from '../../Models/ControlRef';
3
+ export declare const mergePushControl: <T>(state: Form<T>, form: BaseForm<T>, controlRef: ControlRef) => {
4
+ root?: import("../../Models/Controls").FormControl<unknown>;
5
+ };
@@ -1,5 +1,5 @@
1
1
  import { Reactable, EffectsAndSources } from '@reactables/core';
2
- import { ControlChange, AddControl, MarkTouched } from '../Models/Payloads';
2
+ import { ControlChange, AddControl, MarkTouched, PushControl } from '../Models/Payloads';
3
3
  import { ControlRef } from '../Models';
4
4
  import { FormControlConfig, FormArrayConfig, FormGroupConfig, AbstractControlConfig } from '../Models/Configs';
5
5
  import { ValidatorFn, ValidatorAsyncFn } from '../Models/Validators';
@@ -8,6 +8,7 @@ type FbControl<T> = [T, (ValidatorFn | ValidatorFn[])?, (ValidatorAsyncFn | Vali
8
8
  export type RxFormActions = {
9
9
  updateValues: <T>(payload: ControlChange<T>) => void;
10
10
  addControl: (payload: AddControl) => void;
11
+ pushControl: (payload: PushControl) => void;
11
12
  removeControl: (payload: ControlRef) => void;
12
13
  markControlAsPristine: (payload: ControlRef) => void;
13
14
  markControlAsTouched: (payload: MarkTouched) => void;
package/dist/index.js CHANGED
@@ -16,6 +16,7 @@ var DEFAULT_HUB2_FIELDS = {
16
16
  asyncValidateInProgress: {},
17
17
  pending: false,
18
18
  valid: null,
19
+ childrenValid: null,
19
20
  errors: null
20
21
  };
21
22
 
@@ -131,16 +132,9 @@ var generateKey = function (length) {
131
132
  return result;
132
133
  };
133
134
 
134
- var syncValidate = function (form) {
135
- // First check each control for its own validation
136
- var validated = Object.entries(form).reduce(function (acc, _a) {
137
- var _b;
138
- var _c;
139
- var key = _a[0], control = _a[1];
140
- var validatorErrors = ((_c = control.config.validators) === null || _c === void 0 ? void 0 : _c.reduce(function (acc, validator) { return (__assign(__assign({}, acc), validator(control.value))); }, {})) || {};
141
- return __assign(__assign({}, acc), (_b = {}, _b[key] = __assign(__assign({}, control), { validatorErrors: validatorErrors }), _b));
142
- }, {});
143
- return validated;
135
+ var getErrors = function (control, value) {
136
+ var _a;
137
+ return ((_a = control.config.validators) === null || _a === void 0 ? void 0 : _a.reduce(function (acc, validator) { return (__assign(__assign({}, acc), validator(value))); }, {})) || {};
144
138
  };
145
139
 
146
140
  var buildState = function (config, form, controlRef) {
@@ -158,7 +152,7 @@ var buildState = function (config, form, controlRef) {
158
152
  config: config,
159
153
  key: generateKey(5)
160
154
  };
161
- var newForm = __assign(__assign({}, form), (_a = {}, _a[getFormKey(controlRef)] = control, _a));
155
+ var newForm = __assign(__assign({}, form), (_a = {}, _a[getFormKey(controlRef)] = __assign(__assign({}, control), { validatorErrors: getErrors(control, value) }), _a));
162
156
  var controls = config.controls;
163
157
  // Adding controls for Form Group
164
158
  if (controls && !(controls instanceof Array)) {
@@ -177,7 +171,7 @@ var buildFormState = function (config, form, controlRef) {
177
171
  if (form === void 0) { form = { root: null }; }
178
172
  if (controlRef === void 0) { controlRef = []; }
179
173
  return {
180
- form: syncValidate(buildState(config, form, controlRef)),
174
+ form: buildState(config, form, controlRef),
181
175
  action: null
182
176
  };
183
177
  };
@@ -286,6 +280,7 @@ var buildHub2Source = function (rx) {
286
280
  case 'updateValues':
287
281
  controlsToCheck = getControlBranch(action.payload.controlRef, newForm);
288
282
  break;
283
+ case 'pushControl':
289
284
  case 'addControl':
290
285
  var changedControl = getControl(action.payload.controlRef, newForm);
291
286
  if (Array.isArray(changedControl.config.controls)) {
@@ -313,11 +308,6 @@ var buildHub2Source = function (rx) {
313
308
  return sourceForHub2$;
314
309
  };
315
310
 
316
- var getErrors = function (control, value) {
317
- var _a;
318
- return ((_a = control.config.validators) === null || _a === void 0 ? void 0 : _a.reduce(function (acc, validator) { return (__assign(__assign({}, acc), validator(value))); }, {})) || {};
319
- };
320
-
321
311
  var UPDATE_ANCESTOR_VALUES = 'UPDATE_ANCESTOR_VALUES';
322
312
  var updateAncestorValues = function (form, _a) {
323
313
  var _b, _c;
@@ -536,6 +526,28 @@ var addControl = function (state, action) {
536
526
  return { form: ancestorsUpdated, action: action };
537
527
  };
538
528
 
529
+ var pushControl = function (state, action) {
530
+ var newControlRef;
531
+ var _a = action.payload, config = _a.config, controlRef = _a.controlRef;
532
+ var existingControl = getControl(controlRef, state.form);
533
+ if (!existingControl)
534
+ throw 'You are attempting to push to a control that does not exist';
535
+ // If controlRef exists we are adding control to a Form Array
536
+ if (Array.isArray(existingControl.config.controls)) {
537
+ newControlRef = controlRef.concat(existingControl.value.length);
538
+ }
539
+ else {
540
+ throw 'You are attempting to push to a control that is not a Form Array';
541
+ }
542
+ var newForm = buildState(config, state.form, newControlRef);
543
+ var newValue = getControl(newControlRef, newForm).value;
544
+ var ancestorsUpdated = updateAncestorValuesAddControl(newForm, {
545
+ type: UPDATE_ANCESTOR_VALUES_ADD_CONTROL,
546
+ payload: { controlRef: newControlRef, value: newValue }
547
+ });
548
+ return { form: ancestorsUpdated, action: action };
549
+ };
550
+
539
551
  // Same implementation as updateAncestor values except updating pristine values
540
552
  var UPDATE_ANCESTOR_PRISTINE_VALUES = 'UPDATE_ANCESTOR_PRISTINE_VALUES';
541
553
  var updateAncestorPristineValues = function (form, _a) {
@@ -660,7 +672,7 @@ var asyncValidation = function (form, _a) {
660
672
  return __assign(__assign({}, form), updatedSelfAndAncestors);
661
673
  };
662
674
 
663
- var hasErrors$3 = function (errors) {
675
+ var hasErrors$4 = function (errors) {
664
676
  return Object.values(errors).some(function (hasError) { return hasError; });
665
677
  };
666
678
  var mergeBranchErrors = function (form, controlRef) {
@@ -674,7 +686,7 @@ var mergeBranchErrors = function (form, controlRef) {
674
686
  var _b;
675
687
  var key = _a[0], control = _a[1];
676
688
  var errors = __assign(__assign({}, control.validatorErrors), control.asyncValidatorErrors);
677
- var selfValid = !hasErrors$3(errors);
689
+ var selfValid = !hasErrors$4(errors);
678
690
  var childrenValid = true;
679
691
  if (Array.isArray(control.config.controls)) {
680
692
  // If control is a FormArray
@@ -692,7 +704,7 @@ var mergeBranchErrors = function (form, controlRef) {
692
704
  return valid;
693
705
  });
694
706
  }
695
- return __assign(__assign({}, acc), (_b = {}, _b[key] = __assign(__assign({}, control), { errors: errors, valid: selfValid && childrenValid }), _b));
707
+ return __assign(__assign({}, acc), (_b = {}, _b[key] = __assign(__assign({}, control), { errors: errors, valid: selfValid && childrenValid, childrenValid: childrenValid }), _b));
696
708
  }, {});
697
709
  return __assign(__assign({}, form), errorsMerged);
698
710
  };
@@ -726,7 +738,7 @@ var asyncValidationResponseSuccess = function (form, _a) {
726
738
  return mergeBranchErrors(ancestorsUpdated, control.controlRef);
727
739
  };
728
740
 
729
- var hasErrors$2 = function (errors) {
741
+ var hasErrors$3 = function (errors) {
730
742
  return Object.values(errors).some(function (hasError) { return hasError; });
731
743
  };
732
744
  // TODO: update merge errors to not do the entire form but just a subset of it
@@ -738,7 +750,7 @@ var mergeErrors = function (form) {
738
750
  var _b;
739
751
  var key = _a[0], control = _a[1];
740
752
  var errors = __assign(__assign({}, control.validatorErrors), control.asyncValidatorErrors);
741
- var selfValid = !hasErrors$2(errors);
753
+ var selfValid = !hasErrors$3(errors);
742
754
  var childrenValid = true;
743
755
  if (Array.isArray(control.config.controls)) {
744
756
  // If control is a FormArray
@@ -748,7 +760,7 @@ var mergeErrors = function (form) {
748
760
  // If control is a FormGroup
749
761
  childrenValid = Object.keys(control.value).every(function (childKey) { return acc[getFormKey(control.controlRef.concat(childKey))].valid; });
750
762
  }
751
- return __assign(__assign({}, acc), (_b = {}, _b[key] = __assign(__assign({}, control), { errors: errors, valid: selfValid && childrenValid }), _b));
763
+ return __assign(__assign({}, acc), (_b = {}, _b[key] = __assign(__assign({}, control), { errors: errors, valid: selfValid && childrenValid, childrenValid: childrenValid }), _b));
752
764
  }, {});
753
765
  var restoredOrder = Object.keys(errorsMerged)
754
766
  .reverse()
@@ -759,7 +771,7 @@ var mergeErrors = function (form) {
759
771
  return restoredOrder;
760
772
  };
761
773
 
762
- var hasErrors$1 = function (errors) {
774
+ var hasErrors$2 = function (errors) {
763
775
  return Object.values(errors).some(function (hasError) { return hasError; });
764
776
  };
765
777
  var mergeValueUpdated = function (state, form, controlRef) {
@@ -770,7 +782,7 @@ var mergeValueUpdated = function (state, form, controlRef) {
770
782
  var key = getFormKey(control.controlRef);
771
783
  var existingControl = state[key] || structuredClone(DEFAULT_HUB2_FIELDS);
772
784
  var errors = __assign(__assign({}, control.validatorErrors), existingControl.asyncValidatorErrors);
773
- var selfValid = !hasErrors$1(errors);
785
+ var selfValid = !hasErrors$2(errors);
774
786
  var childrenValid = true;
775
787
  if (Array.isArray(control.config.controls)) {
776
788
  // If control is a FormArray
@@ -788,12 +800,12 @@ var mergeValueUpdated = function (state, form, controlRef) {
788
800
  return valid;
789
801
  });
790
802
  }
791
- return __assign(__assign({}, acc), (_a = {}, _a[key] = __assign(__assign(__assign({}, existingControl), control), { errors: errors, valid: selfValid && childrenValid }), _a));
803
+ return __assign(__assign({}, acc), (_a = {}, _a[key] = __assign(__assign(__assign({}, existingControl), control), { errors: errors, valid: selfValid && childrenValid, childrenValid: childrenValid }), _a));
792
804
  }, {});
793
805
  return __assign(__assign({}, state), controlBranch);
794
806
  };
795
807
 
796
- var hasErrors = function (errors) {
808
+ var hasErrors$1 = function (errors) {
797
809
  return Object.values(errors).some(function (hasError) { return hasError; });
798
810
  };
799
811
  var mergeRemoveControl = function (state, form, controlRef) {
@@ -808,7 +820,7 @@ var mergeRemoveControl = function (state, form, controlRef) {
808
820
  var existingControl = existingBranch.find(function (control) { return baseControl.key === control.key; }) ||
809
821
  structuredClone(DEFAULT_HUB2_FIELDS);
810
822
  var errors = __assign(__assign({}, baseControl.validatorErrors), existingControl.asyncValidatorErrors);
811
- var selfValid = !hasErrors(errors);
823
+ var selfValid = !hasErrors$1(errors);
812
824
  var childrenValid = true;
813
825
  if (Array.isArray(baseControl.config.controls)) {
814
826
  // If control is a FormArray
@@ -826,7 +838,7 @@ var mergeRemoveControl = function (state, form, controlRef) {
826
838
  return valid;
827
839
  });
828
840
  }
829
- return __assign(__assign({}, acc), (_a = {}, _a[key] = __assign(__assign(__assign({}, existingControl), baseControl), { errors: errors, valid: selfValid && childrenValid }), _a));
841
+ return __assign(__assign({}, acc), (_a = {}, _a[key] = __assign(__assign(__assign({}, existingControl), baseControl), { errors: errors, valid: selfValid && childrenValid, childrenValid: childrenValid }), _a));
830
842
  }, {});
831
843
  var removedControls = __assign({}, state);
832
844
  descendants.forEach(function (control) {
@@ -844,6 +856,46 @@ var mergeTouchUpdated = function (state, form, controlRef) {
844
856
  return __assign(__assign({}, state), controlBranch);
845
857
  };
846
858
 
859
+ var hasErrors = function (errors) {
860
+ return Object.values(errors).some(function (hasError) { return hasError; });
861
+ };
862
+ var mergePushControl = function (state, form, controlRef) {
863
+ var baseFormArray = getControl(controlRef, form);
864
+ //If Form Array
865
+ // use the added control (last index)
866
+ // merge descendants with default stuff
867
+ var newItemIndex = baseFormArray.value.length - 1;
868
+ var descendants = getDescendantControls(controlRef.concat(newItemIndex), form);
869
+ var mergedDescendants = mergeErrors(descendants.reduce(function (acc, control) {
870
+ var _a;
871
+ var formKey = getFormKey(control.controlRef);
872
+ return __assign(__assign({}, acc), (_a = {}, _a[formKey] = __assign(__assign({}, control), structuredClone(DEFAULT_HUB2_FIELDS)), _a));
873
+ }, {}));
874
+ var ancestors = getAncestorControls(controlRef, state)
875
+ .reverse()
876
+ .reduce(function (acc, control, index, arr) {
877
+ var _a, _b;
878
+ var formKey = getFormKey(control.controlRef);
879
+ var errors = __assign(__assign({}, form[formKey].validatorErrors), control.asyncValidatorErrors);
880
+ if (!control.childrenValid)
881
+ // If the ancestor control's children were not valid, pushing an item won't change its valid status
882
+ return __assign(__assign({}, acc), (_a = {}, _a[formKey] = __assign(__assign(__assign({}, control), form[formKey]), { errors: errors }), _a));
883
+ var selfValid = !hasErrors(errors);
884
+ var childrenValid = true;
885
+ if (index === 0) {
886
+ childrenValid =
887
+ control.childrenValid &&
888
+ mergedDescendants[getFormKey(controlRef.concat(newItemIndex))].valid;
889
+ }
890
+ else {
891
+ childrenValid = control.childrenValid && arr[index - 1].valid;
892
+ }
893
+ return __assign(__assign({}, acc), (_b = {}, _b[formKey] = __assign(__assign(__assign({}, control), form[formKey]), { errors: errors, valid: selfValid && childrenValid, childrenValid: childrenValid }), _b));
894
+ }, {});
895
+ var controlBranchUpdated = __assign(__assign({}, ancestors), mergedDescendants);
896
+ return __assign(__assign({}, state), controlBranchUpdated);
897
+ };
898
+
847
899
  var formChange = function (state, _a) {
848
900
  if (state === void 0) { state = null; }
849
901
  var _b = _a.payload, form = _b.form, action = _b.action;
@@ -855,6 +907,8 @@ var formChange = function (state, _a) {
855
907
  }, {}));
856
908
  }
857
909
  switch (action === null || action === void 0 ? void 0 : action.type) {
910
+ case 'pushControl':
911
+ return mergePushControl(state, form, action.payload.controlRef);
858
912
  case 'addControl':
859
913
  case 'updateValues':
860
914
  return mergeValueUpdated(state, form, action.payload.controlRef);
@@ -900,6 +954,7 @@ var build = function (config, options) {
900
954
  updateValues: updateValues,
901
955
  removeControl: removeControl,
902
956
  addControl: addControl,
957
+ pushControl: pushControl,
903
958
  markControlAsPristine: markControlAsPristine,
904
959
  markControlAsTouched: markControlAsTouched,
905
960
  markControlAsUntouched: markControlAsUntouched,
package/package.json CHANGED
@@ -14,12 +14,12 @@
14
14
  "author": "David Lai",
15
15
  "license": "ISC",
16
16
  "dependencies": {
17
- "@reactables/core": "^0.4.6-alpha.0",
17
+ "@reactables/core": "^0.5.0-alpha.0",
18
18
  "lodash.clonedeep": "^4.5.0",
19
19
  "lodash.isequal": "^4.5.0"
20
20
  },
21
21
  "peerDependencies": {
22
22
  "rxjs": "^6.0.0 || ^7.0.0"
23
23
  },
24
- "version": "0.4.6-alpha.0"
24
+ "version": "0.5.0-alpha.0"
25
25
  }
@@ -1,2 +0,0 @@
1
- import { BaseForm } from '../../Models/Controls';
2
- export declare const syncValidate: <T>(form: BaseForm<T>) => BaseForm<T>;
@@ -1 +0,0 @@
1
- export {};