@reactables/forms 0.4.3-alpha.1 → 0.4.5-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.
@@ -9,12 +9,10 @@ export interface BaseControl<T> {
9
9
  dirty: boolean;
10
10
  touched: boolean;
11
11
  validatorErrors: FormErrors;
12
- validatorsValid: boolean;
13
12
  config: AbstractControlConfig;
14
13
  key: string;
15
14
  }
16
15
  interface AsyncFields {
17
- asyncValidatorsValid: boolean;
18
16
  asyncValidatorErrors: FormErrors;
19
17
  asyncValidateInProgress: {
20
18
  [key: string | number]: boolean;
@@ -38,7 +36,7 @@ export interface BaseForm<T> {
38
36
  [key: string]: BaseControl<unknown>;
39
37
  }
40
38
  export interface Form<T> {
41
- root: FormControl<T>;
39
+ root?: FormControl<T>;
42
40
  [key: string]: FormControl<unknown>;
43
41
  }
44
42
  export {};
@@ -0,0 +1,3 @@
1
+ import { BaseControl } from '../../Models/Controls';
2
+ import { FormErrors } from '../../Models';
3
+ export declare const getErrors: <T>(control: BaseControl<T>, value: T) => FormErrors;
@@ -4,6 +4,4 @@ export { markControlAsUntouched } from './markControlAsUntouched';
4
4
  export { removeControl } from './removeControl';
5
5
  export { resetControl } from './resetControl';
6
6
  export { syncValidate } from './syncValidate';
7
- export { updateDirty } from './updateDirty';
8
7
  export { updateValues } from './updateValues';
9
- export { buildHub1Reducer } from './buildHub1Reducer';
@@ -1,5 +1,5 @@
1
1
  import { Action } from '@reactables/core';
2
2
  import { BaseForm } from '../../Models/Controls';
3
- import { ControlRef } from '../../Models/ControlRef';
3
+ import { ControlChange } from '../../Models/Payloads';
4
4
  export declare const UPDATE_ANCESTOR_VALUES = "UPDATE_ANCESTOR_VALUES";
5
- export declare const updateAncestorValues: <T>(form: BaseForm<T>, { payload: controlRef }: Action<ControlRef>) => BaseForm<T>;
5
+ export declare const updateAncestorValues: <T>(form: BaseForm<T>, { payload: { controlRef, value } }: Action<ControlChange<unknown>>) => BaseForm<T>;
@@ -0,0 +1,5 @@
1
+ import { Action } from '@reactables/core';
2
+ import { BaseForm } from '../../Models/Controls';
3
+ import { ControlChange } from '../../Models/Payloads';
4
+ export declare const UPDATE_ANCESTOR_VALUES_ADD_CONTROL = "UPDATE_ANCESTOR_VALUES_ADD_CONTROL";
5
+ export declare const updateAncestorValuesAddControl: <T>(form: BaseForm<T>, { payload: { controlRef, value } }: Action<ControlChange<unknown>>) => BaseForm<T>;
@@ -0,0 +1,5 @@
1
+ import { Action } from '@reactables/core';
2
+ import { BaseForm } from '../../Models/Controls';
3
+ import { ControlRef } from '../../Models/ControlRef';
4
+ export declare const UPDATE_ANCESTOR_VALUES_REMOVE_CONTROL = "UPDATE_ANCESTOR_VALUES_REMOVE_CONTROL";
5
+ export declare const updateAncestorValuesRemoveControl: <T>(form: BaseForm<T>, { payload: controlRef }: Action<ControlRef>) => BaseForm<T>;
@@ -0,0 +1,3 @@
1
+ import { Form } from '../../Models/Controls';
2
+ import { ControlRef } from '../../Models';
3
+ export declare const mergeBranchErrors: <T>(form: Form<T>, controlRef: ControlRef) => Form<T>;
@@ -0,0 +1,3 @@
1
+ import { Form, BaseForm } from '../../Models/Controls';
2
+ import { ControlRef } from '../../Models/ControlRef';
3
+ export declare const mergeRemoveControl: <T>(state: Form<T>, form: BaseForm<T>, controlRef: ControlRef) => Form<T>;
@@ -0,0 +1,6 @@
1
+ import { Form, BaseForm, FormControl } from '../../Models/Controls';
2
+ import { ControlRef } from '../../Models/ControlRef';
3
+ export declare const mergeTouchUpdated: <T>(state: Form<T>, form: BaseForm<T>, controlRef: ControlRef) => {
4
+ [x: string]: FormControl<unknown>;
5
+ root?: FormControl<T>;
6
+ };
@@ -0,0 +1,3 @@
1
+ import { Form, BaseForm } from '../../Models/Controls';
2
+ import { ControlRef } from '../../Models/ControlRef';
3
+ export declare const mergeValueUpdated: <T>(state: Form<T>, form: BaseForm<T>, controlRef: ControlRef) => Form<T>;
package/dist/index.js CHANGED
@@ -122,44 +122,14 @@ var generateKey = function (length) {
122
122
  return result;
123
123
  };
124
124
 
125
- // Includes the original control of interest unless excludeSelf === true
126
- var getDescendantControls = function (controlRef, form, excludeSelf) {
127
- if (excludeSelf === void 0) { excludeSelf = false; }
128
- var result = Object.entries(form)
129
- .filter(function (_a) {
130
- var key = _a[0];
131
- if (!controlRef.length)
132
- return true;
133
- var childRef = key.split('.');
134
- return controlRef.every(function (refKey, index) {
135
- return refKey == childRef[index];
136
- });
137
- })
138
- .map(function (entry) { return entry[1]; });
139
- return result.filter(function (control) {
140
- return excludeSelf ? getFormKey(control.controlRef) !== getFormKey(controlRef) : true;
141
- });
142
- };
143
-
144
125
  var syncValidate = function (form) {
145
126
  // First check each control for its own validation
146
- var baseValidation = Object.entries(form).reduce(function (acc, _a) {
127
+ var validated = Object.entries(form).reduce(function (acc, _a) {
147
128
  var _b;
148
129
  var _c;
149
130
  var key = _a[0], control = _a[1];
150
131
  var validatorErrors = ((_c = control.config.validators) === null || _c === void 0 ? void 0 : _c.reduce(function (acc, validator) { return (__assign(__assign({}, acc), validator(control.value))); }, {})) || {};
151
- var validatorsValid = !Object.values(validatorErrors).some(function (err) { return err; });
152
- return __assign(__assign({}, acc), (_b = {}, _b[key] = __assign(__assign({}, control), { validatorErrors: validatorErrors, validatorsValid: validatorsValid }), _b));
153
- }, {});
154
- // Then check each controls children to see if there are errors
155
- var validated = Object.entries(baseValidation).reduce(function (acc, _a) {
156
- var _b;
157
- var key = _a[0], control = _a[1];
158
- var validatorsValid = getDescendantControls(control.controlRef, baseValidation).every(function (_a) {
159
- var validatorsValid = _a.validatorsValid;
160
- return validatorsValid;
161
- });
162
- return __assign(__assign({}, acc), (_b = {}, _b[key] = __assign(__assign({}, control), { validatorsValid: validatorsValid }), _b));
132
+ return __assign(__assign({}, acc), (_b = {}, _b[key] = __assign(__assign({}, control), { validatorErrors: validatorErrors }), _b));
163
133
  }, {});
164
134
  return validated;
165
135
  };
@@ -176,7 +146,6 @@ var buildState = function (config, form, controlRef) {
176
146
  value: value,
177
147
  controlRef: controlRef,
178
148
  validatorErrors: {},
179
- validatorsValid: null,
180
149
  config: config,
181
150
  key: generateKey(5)
182
151
  };
@@ -193,13 +162,13 @@ var buildState = function (config, form, controlRef) {
193
162
  // Adding controls for Form Array
194
163
  newForm = config.controls.reduce(function (acc, controlConfig, index) { return buildState(controlConfig, acc, controlRef.concat(index)); }, newForm);
195
164
  }
196
- return syncValidate(newForm);
165
+ return newForm;
197
166
  };
198
167
  var buildFormState = function (config, form, controlRef) {
199
168
  if (form === void 0) { form = { root: null }; }
200
169
  if (controlRef === void 0) { controlRef = []; }
201
170
  return {
202
- form: buildState(config, form, controlRef),
171
+ form: syncValidate(buildState(config, form, controlRef)),
203
172
  action: null
204
173
  };
205
174
  };
@@ -229,10 +198,39 @@ var getAncestorControls = function (controlRef, form, excludeSelf) {
229
198
  });
230
199
  };
231
200
 
201
+ // Includes the original control of interest unless excludeSelf === true
202
+ var getDescendantControls = function (controlRef, form, excludeSelf) {
203
+ if (excludeSelf === void 0) { excludeSelf = false; }
204
+ if (!controlRef.length) {
205
+ return Object.values(form).filter(function (_a) {
206
+ var controlRef = _a.controlRef;
207
+ return excludeSelf ? controlRef.length !== 0 : true;
208
+ });
209
+ }
210
+ var control = getControl(controlRef, form);
211
+ var value = control.value, config = control.config;
212
+ var descendants;
213
+ if (Array.isArray(config.controls)) {
214
+ // If control is a Form Array
215
+ descendants = value.reduce(function (acc, item, index) {
216
+ return acc.concat(getDescendantControls(controlRef.concat(index), form));
217
+ }, []);
218
+ }
219
+ else if (config.controls) {
220
+ // If control is a Form Group
221
+ descendants = Object.keys(value).reduce(function (acc, key) {
222
+ return acc.concat(getDescendantControls(controlRef.concat(key), form));
223
+ }, []);
224
+ }
225
+ if (excludeSelf)
226
+ return descendants;
227
+ return [control].concat(descendants || []);
228
+ };
229
+
232
230
  var getControlBranch = function (controlRef, form) {
233
231
  var ancestors = getAncestorControls(controlRef, form);
234
232
  var childControls = getDescendantControls(controlRef, form).slice(1);
235
- return ancestors.concat(childControls);
233
+ return ancestors.concat(childControls).sort(function (a, b) { return a.controlRef.length - b.controlRef.length; });
236
234
  };
237
235
 
238
236
  var getScopedEffectsForControl = function (formControl) {
@@ -306,49 +304,40 @@ var buildHub2Source = function (rx) {
306
304
  return sourceForHub2$;
307
305
  };
308
306
 
307
+ var getErrors = function (control, value) {
308
+ var _a;
309
+ return ((_a = control.config.validators) === null || _a === void 0 ? void 0 : _a.reduce(function (acc, validator) { return (__assign(__assign({}, acc), validator(value))); }, {})) || {};
310
+ };
311
+
309
312
  var UPDATE_ANCESTOR_VALUES = 'UPDATE_ANCESTOR_VALUES';
310
313
  var updateAncestorValues = function (form, _a) {
311
- var _b;
312
- var controlRef = _a.payload;
314
+ var _b, _c;
315
+ var _d = _a.payload, controlRef = _d.controlRef, value = _d.value;
313
316
  if (controlRef.length) {
314
317
  var parentRef = controlRef.slice(0, -1);
315
- var parentKey = getFormKey(parentRef);
316
- var siblingControls = getDescendantControls(parentRef, form).filter(
317
- // Out of descendants we only need the siblings
318
- function (control) { return control.controlRef.length === controlRef.length; });
318
+ var parentControl = getControl(parentRef, form);
319
+ var parentFormKey = getFormKey(parentControl.controlRef);
320
+ var childKey_1 = controlRef.slice(-1)[0];
319
321
  var newValue = void 0;
320
322
  // If parent is a Form Array
321
- if (Array.isArray(form[parentKey].value)) {
322
- newValue = siblingControls
323
- .slice()
324
- .sort(function (a, b) { return a.controlRef.at(-1) - b.controlRef.at(-1); })
325
- .map(function (control) { return control.value; });
323
+ if (Array.isArray(parentControl.value)) {
324
+ newValue = parentControl.value.map(function (item, index) {
325
+ return index === childKey_1 ? value : item;
326
+ });
326
327
  }
327
328
  else {
328
329
  // If parent is a Form Group
329
- newValue = siblingControls.reduce(function (acc, _a) {
330
- var _b;
331
- var controlRef = _a.controlRef, value = _a.value;
332
- return __assign(__assign({}, acc), (_b = {}, _b[controlRef.at(-1)] = value, _b));
333
- }, {});
330
+ newValue = __assign(__assign({}, parentControl.value), (_b = {}, _b[childKey_1] = value, _b));
334
331
  }
335
- var newParentControl = __assign(__assign({}, form[parentKey]), { value: newValue });
336
- return updateAncestorValues(__assign(__assign({}, form), (_b = {}, _b[parentKey] = newParentControl, _b)), {
332
+ var newParentControl = __assign(__assign({}, parentControl), { validatorErrors: getErrors(parentControl, newValue), value: newValue, dirty: !isEqual__default["default"](newValue, parentControl.pristineValue) });
333
+ return updateAncestorValues(__assign(__assign({}, form), (_c = {}, _c[parentFormKey] = newParentControl, _c)), {
337
334
  type: UPDATE_ANCESTOR_VALUES,
338
- payload: parentRef
335
+ payload: { controlRef: parentRef, value: newValue }
339
336
  });
340
337
  }
341
338
  return form;
342
339
  };
343
340
 
344
- var updateDirty = function (form) {
345
- return Object.entries(form).reduce(function (acc, _a) {
346
- var _b;
347
- var key = _a[0], control = _a[1];
348
- return __assign(__assign({}, acc), (_b = {}, _b[key] = __assign(__assign({}, control), { dirty: !isEqual__default["default"](control.value, control.pristineValue) }), _b));
349
- }, {});
350
- };
351
-
352
341
  var isChildRef = function (controlRef, parentRef) {
353
342
  return (parentRef.every(function (key, index) { return controlRef[index] === key; }) &&
354
343
  controlRef.length === parentRef.length + 1);
@@ -357,12 +346,14 @@ var isChildRef = function (controlRef, parentRef) {
357
346
  var UPDATE_DESCENDANT_VALUES = 'UPDATE_DESCENDANT_VALUES';
358
347
  var updateDescendants = function (form, _a) {
359
348
  var _b = _a.payload, controlRef = _b.controlRef, value = _b.value;
360
- var result = Object.entries(form).reduce(function (acc, _a) {
349
+ var descendants = getDescendantControls(controlRef, form, true).map(function (control) { return [getFormKey(control.controlRef), control]; });
350
+ var result = descendants.reduce(function (acc, _a) {
361
351
  var _b;
362
352
  var key = _a[0], control = _a[1];
363
353
  if (isChildRef(control.controlRef, controlRef)) {
364
354
  var childValue = value[control.controlRef.at(-1)];
365
- acc = __assign(__assign({}, acc), (_b = {}, _b[key] = __assign(__assign({}, control), { value: childValue }), _b));
355
+ var validatorErrors = getErrors(control, value);
356
+ acc = __assign(__assign({}, acc), (_b = {}, _b[key] = __assign(__assign({}, control), { value: childValue, validatorErrors: validatorErrors, dirty: !isEqual__default["default"](childValue, control.pristineValue) }), _b));
366
357
  var configControls = control.config.controls;
367
358
  if (configControls) {
368
359
  acc = updateDescendants(acc, {
@@ -383,7 +374,8 @@ var updateValues = function (_a, action) {
383
374
  var _c = action.payload, controlRef = _c.controlRef, value = _c.value;
384
375
  // Update its own value
385
376
  var ctrlKey = getFormKey(controlRef);
386
- var result = __assign(__assign({}, form), (_b = {}, _b[ctrlKey] = __assign(__assign({}, form[ctrlKey]), { value: value }), _b));
377
+ var validatorErrors = getErrors(form[ctrlKey], value);
378
+ var result = __assign(__assign({}, form), (_b = {}, _b[ctrlKey] = __assign(__assign({}, form[ctrlKey]), { validatorErrors: validatorErrors, dirty: !isEqual__default["default"](value, form[ctrlKey].pristineValue), value: value }), _b));
387
379
  var configControls = form[ctrlKey].config.controls;
388
380
  // Update its children
389
381
  if (configControls) {
@@ -399,10 +391,38 @@ var updateValues = function (_a, action) {
399
391
  if (controlRef.length) {
400
392
  result = updateAncestorValues(result, {
401
393
  type: UPDATE_ANCESTOR_VALUES,
402
- payload: controlRef
394
+ payload: { controlRef: controlRef, value: value }
395
+ });
396
+ }
397
+ return { form: result, action: action };
398
+ };
399
+
400
+ var UPDATE_ANCESTOR_VALUES_REMOVE_CONTROL = 'UPDATE_ANCESTOR_VALUES_REMOVE_CONTROL';
401
+ var updateAncestorValuesRemoveControl = function (form, _a) {
402
+ var _b;
403
+ var controlRef = _a.payload;
404
+ if (controlRef.length) {
405
+ var parentRef = controlRef.slice(0, -1);
406
+ var parentControl = getControl(parentRef, form);
407
+ var parentFormKey = getFormKey(parentControl.controlRef);
408
+ var childKey_1 = controlRef.slice(-1)[0];
409
+ var newValue = void 0;
410
+ // If parent is a Form Array
411
+ if (Array.isArray(parentControl.value)) {
412
+ newValue = parentControl.value.filter(function (item, index) { return index !== childKey_1; });
413
+ }
414
+ else {
415
+ // If parent is a Form Group
416
+ newValue = __assign({}, parentControl.value);
417
+ delete newValue[childKey_1];
418
+ }
419
+ var newParentControl = __assign(__assign({}, parentControl), { value: newValue, validatorErrors: getErrors(parentControl, newValue), dirty: !isEqual__default["default"](newValue, parentControl.pristineValue) });
420
+ return updateAncestorValues(__assign(__assign({}, form), (_b = {}, _b[parentFormKey] = newParentControl, _b)), {
421
+ type: UPDATE_ANCESTOR_VALUES,
422
+ payload: { controlRef: parentRef, value: newValue }
403
423
  });
404
424
  }
405
- return { form: syncValidate(updateDirty(result)), action: action };
425
+ return form;
406
426
  };
407
427
 
408
428
  var removeControl = function (_a, action) {
@@ -416,14 +436,16 @@ var removeControl = function (_a, action) {
416
436
  return { form: form, action: action };
417
437
  var parentRef = controlRef.slice(0, -1);
418
438
  var parentIsFormArray = Array.isArray(getControl(parentRef, form).config.controls);
439
+ var descendantkeys = getDescendantControls(controlRef, form).map(function (_a) {
440
+ var controlRef = _a.controlRef;
441
+ return getFormKey(controlRef);
442
+ });
443
+ var controlsRemoved = __assign({}, form);
444
+ descendantkeys.forEach(function (key) {
445
+ delete controlsRemoved[key];
446
+ });
419
447
  // Remove control and all descendants
420
- var controlRemoved = Object.entries(form)
421
- .filter(function (_a) {
422
- _a[0]; var control = _a[1];
423
- return !(control.controlRef.length > parentRef.length &&
424
- controlRef.every(function (key, index) { return key === control.controlRef[index]; }));
425
- })
426
- .reduce(function (acc, _a) {
448
+ var controlRemoved = Object.entries(controlsRemoved).reduce(function (acc, _a) {
427
449
  var _b, _c;
428
450
  var key = _a[0], control = _a[1];
429
451
  // May need to reindex array items of removed control
@@ -446,14 +468,41 @@ var removeControl = function (_a, action) {
446
468
  return __assign(__assign({}, acc), (_c = {}, _c[key] = control, _c));
447
469
  }, {});
448
470
  return {
449
- form: syncValidate(updateDirty(updateAncestorValues(controlRemoved, {
450
- type: UPDATE_ANCESTOR_VALUES,
471
+ form: updateAncestorValuesRemoveControl(controlRemoved, {
472
+ type: UPDATE_ANCESTOR_VALUES_REMOVE_CONTROL,
451
473
  payload: controlRef
452
- }))),
474
+ }),
453
475
  action: action
454
476
  };
455
477
  };
456
478
 
479
+ var UPDATE_ANCESTOR_VALUES_ADD_CONTROL = 'UPDATE_ANCESTOR_VALUES_ADD_CONTROL';
480
+ var updateAncestorValuesAddControl = function (form, _a) {
481
+ var _b, _c;
482
+ var _d = _a.payload, controlRef = _d.controlRef, value = _d.value;
483
+ if (controlRef.length) {
484
+ var parentRef = controlRef.slice(0, -1);
485
+ var parentControl = getControl(parentRef, form);
486
+ var parentFormKey = getFormKey(parentControl.controlRef);
487
+ var childKey = controlRef.slice(-1)[0];
488
+ var newValue = void 0;
489
+ // If parent is a Form Array
490
+ if (Array.isArray(parentControl.value)) {
491
+ newValue = parentControl.value.concat(value);
492
+ }
493
+ else {
494
+ // If parent is a Form Group
495
+ newValue = __assign(__assign({}, form[parentFormKey].value), (_b = {}, _b[childKey] = value, _b));
496
+ }
497
+ var newParentControl = __assign(__assign({}, parentControl), { value: newValue, validatorErrors: getErrors(parentControl, newValue), dirty: !isEqual__default["default"](newValue, parentControl.pristineValue) });
498
+ return updateAncestorValues(__assign(__assign({}, form), (_c = {}, _c[parentFormKey] = newParentControl, _c)), {
499
+ type: UPDATE_ANCESTOR_VALUES,
500
+ payload: { controlRef: parentRef, value: newValue }
501
+ });
502
+ }
503
+ return form;
504
+ };
505
+
457
506
  var addControl = function (state, action) {
458
507
  var newControlRef;
459
508
  var _a = action.payload, config = _a.config, controlRef = _a.controlRef;
@@ -470,11 +519,12 @@ var addControl = function (state, action) {
470
519
  newControlRef = controlRef;
471
520
  }
472
521
  var newForm = buildState(config, state.form, newControlRef);
473
- var ancestorsUpdated = updateAncestorValues(newForm, {
474
- type: UPDATE_ANCESTOR_VALUES,
475
- payload: newControlRef
522
+ var newValue = getControl(newControlRef, newForm).value;
523
+ var ancestorsUpdated = updateAncestorValuesAddControl(newForm, {
524
+ type: UPDATE_ANCESTOR_VALUES_ADD_CONTROL,
525
+ payload: { controlRef: newControlRef, value: newValue }
476
526
  });
477
- return { form: syncValidate(updateDirty(ancestorsUpdated)), action: action };
527
+ return { form: ancestorsUpdated, action: action };
478
528
  };
479
529
 
480
530
  // Same implementation as updateAncestor values except updating pristine values
@@ -504,7 +554,7 @@ var updateAncestorPristineValues = function (form, _a) {
504
554
  return __assign(__assign({}, acc), (_b = {}, _b[controlRef.at(-1)] = pristineValue, _b));
505
555
  }, {});
506
556
  }
507
- var newParentControl = __assign(__assign({}, form[parentKey]), { pristineValue: newValue });
557
+ var newParentControl = __assign(__assign({}, form[parentKey]), { pristineValue: newValue, dirty: isEqual__default["default"](form[parentKey].value, newValue) });
508
558
  return updateAncestorPristineValues(__assign(__assign({}, form), (_b = {}, _b[parentKey] = newParentControl, _b)), {
509
559
  type: UPDATE_ANCESTOR_PRISTINE_VALUES,
510
560
  payload: parentRef
@@ -516,35 +566,29 @@ var updateAncestorPristineValues = function (form, _a) {
516
566
  var markControlAsPristine = function (_a, action) {
517
567
  var form = _a.form;
518
568
  var controlRef = action.payload;
519
- var descendants = getDescendantControls(controlRef, form);
520
- var result = Object.entries(form).reduce(function (acc, _a) {
521
- var _b;
522
- var key = _a[0], control = _a[1];
523
- var isDescendant = descendants.includes(control);
524
- return __assign(__assign({}, acc), (_b = {}, _b[key] = isDescendant
525
- ? __assign(__assign({}, control), { pristineValue: control.value, dirty: false }) : control, _b));
569
+ var descendants = getDescendantControls(controlRef, form).reduce(function (acc, control) {
570
+ var _a;
571
+ return (__assign(__assign({}, acc), (_a = {}, _a[getFormKey(control.controlRef)] = __assign(__assign({}, control), { dirty: false, pristineValue: control.value }), _a)));
526
572
  }, {});
573
+ var result = __assign(__assign({}, form), descendants);
527
574
  if (controlRef.length) {
528
575
  result = updateAncestorPristineValues(result, {
529
576
  type: UPDATE_ANCESTOR_PRISTINE_VALUES,
530
577
  payload: controlRef
531
578
  });
532
579
  }
533
- return { form: updateDirty(result), action: action };
580
+ return { form: result, action: action };
534
581
  };
535
582
 
536
583
  var markControlAsTouched = function (_a, action) {
537
584
  var form = _a.form;
538
585
  var _b = action.payload, controlRef = _b.controlRef, markAll = _b.markAll;
539
- var controls = markAll
540
- ? getControlBranch(controlRef, form)
541
- : getAncestorControls(controlRef, form);
586
+ var controls = (markAll ? getControlBranch(controlRef, form) : getAncestorControls(controlRef, form)).reduce(function (acc, control) {
587
+ var _a;
588
+ return (__assign(__assign({}, acc), (_a = {}, _a[getFormKey(control.controlRef)] = __assign(__assign({}, control), { touched: true }), _a)));
589
+ }, {});
542
590
  return {
543
- form: Object.entries(form).reduce(function (acc, _a) {
544
- var _b;
545
- var key = _a[0], control = _a[1];
546
- return (__assign(__assign({}, acc), (_b = {}, _b[key] = __assign(__assign({}, control), { touched: controls.includes(control) ? true : control.touched }), _b)));
547
- }, {}),
591
+ form: __assign(__assign({}, form), controls),
548
592
  action: action
549
593
  };
550
594
  };
@@ -553,12 +597,11 @@ var markControlAsUntouched = function (_a, action) {
553
597
  var _b;
554
598
  var form = _a.form;
555
599
  var controlRef = action.payload;
556
- var descendants = getDescendantControls(controlRef, form);
557
- var result = Object.entries(form).reduce(function (acc, _a) {
558
- var _b;
559
- var key = _a[0], control = _a[1];
560
- return (__assign(__assign({}, acc), (_b = {}, _b[key] = __assign(__assign({}, control), { touched: descendants.includes(control) ? false : control.touched }), _b)));
600
+ var result = getDescendantControls(controlRef, form).reduce(function (acc, control) {
601
+ var _a;
602
+ return (__assign(__assign({}, acc), (_a = {}, _a[getFormKey(control.controlRef)] = __assign(__assign({}, control), { touched: false }), _a)));
561
603
  }, {});
604
+ result = __assign(__assign({}, form), result);
562
605
  // Update ancestors
563
606
  var currentRef = controlRef;
564
607
  var key;
@@ -584,51 +627,65 @@ var resetControl = function (_a, action) {
584
627
  return __assign(__assign({}, acc), (_b = {}, _b[key] = control, _b));
585
628
  }, {});
586
629
  var restoredControls = buildState(controlToReset.config, descendantsRemoved, controlToReset.controlRef);
630
+ var restoredControlValue = getControl(controlRef, restoredControls).value;
587
631
  return {
588
- form: updateDirty(syncValidate(updateAncestorValues(restoredControls, {
632
+ form: updateAncestorValues(restoredControls, {
589
633
  type: UPDATE_ANCESTOR_VALUES,
590
- payload: controlRef
591
- }))),
634
+ payload: { controlRef: controlRef, value: restoredControlValue }
635
+ }),
592
636
  action: action
593
637
  };
594
638
  };
595
639
 
596
640
  var asyncValidation = function (form, _a) {
597
641
  var controlRef = _a.payload.controlRef;
598
- var ancestors = getAncestorControls(controlRef, form);
599
- var result = Object.entries(form).reduce(function (acc, _a) {
600
- var _b, _c;
601
- var key = _a[0], control = _a[1];
602
- if (ancestors.includes(control)) {
603
- var isChangedControl = getFormKey(control.controlRef) === getFormKey(controlRef);
604
- return __assign(__assign({}, acc), (_b = {}, _b[key] = __assign(__assign({}, control), { pending: true, asyncValidateInProgress: isChangedControl
605
- ? __assign({}, control.config.asyncValidators.reduce(function (acc, _, index) {
606
- var _a;
607
- return (__assign(__assign({}, acc), (_a = {}, _a[index] = true, _a)));
608
- }, {})) : control.asyncValidateInProgress }), _b));
609
- }
610
- return __assign(__assign({}, acc), (_c = {}, _c[key] = control, _c));
642
+ var updatedSelfAndAncestors = getAncestorControls(controlRef, form).reduce(function (acc, control) {
643
+ var _a;
644
+ var isChangedControl = getFormKey(control.controlRef) === getFormKey(controlRef);
645
+ return __assign(__assign({}, acc), (_a = {}, _a[getFormKey(control.controlRef)] = __assign(__assign({}, control), { pending: true, asyncValidateInProgress: isChangedControl
646
+ ? __assign({}, control.config.asyncValidators.reduce(function (acc, _, index) {
647
+ var _a;
648
+ return (__assign(__assign({}, acc), (_a = {}, _a[index] = true, _a)));
649
+ }, {})) : control.asyncValidateInProgress }), _a));
611
650
  }, {});
612
- return result;
651
+ return __assign(__assign({}, form), updatedSelfAndAncestors);
613
652
  };
614
653
 
615
- var hasErrors = function (errors) {
654
+ var hasErrors$1 = function (errors) {
616
655
  return Object.values(errors).some(function (hasError) { return hasError; });
617
656
  };
618
- var mergeErrors = function (form) {
619
- var errorsMerged = Object.entries(form).reduce(function (acc, _a) {
620
- var _b;
621
- var key = _a[0], control = _a[1];
622
- var errors = __assign(__assign({}, control.validatorErrors), control.asyncValidatorErrors);
623
- return __assign(__assign({}, acc), (_b = {}, _b[key] = __assign(__assign({}, control), { errors: errors, valid: !hasErrors(errors) }), _b));
657
+ var mergeBranchErrors = function (form, controlRef) {
658
+ var controlBranch = getControlBranch(controlRef, form).reduce(function (acc, ctrl) {
659
+ var _a;
660
+ return __assign(__assign({}, acc), (_a = {}, _a[getFormKey(ctrl.controlRef)] = ctrl, _a));
624
661
  }, {});
625
- var childrenErrorsChecked = Object.entries(errorsMerged).reduce(function (acc, _a) {
662
+ var errorsMerged = Object.entries(controlBranch)
663
+ .reverse()
664
+ .reduce(function (acc, _a) {
626
665
  var _b;
627
666
  var key = _a[0], control = _a[1];
628
- return __assign(__assign({}, acc), (_b = {}, _b[key] = __assign(__assign({}, control), { valid: control.valid &&
629
- getDescendantControls(control.controlRef, errorsMerged).every(function (control) { return control.valid; }) }), _b));
667
+ var errors = __assign(__assign({}, control.validatorErrors), control.asyncValidatorErrors);
668
+ var selfValid = !hasErrors$1(errors);
669
+ var childrenValid = true;
670
+ if (Array.isArray(control.config.controls)) {
671
+ // If control is a FormArray
672
+ childrenValid = control.value.every(function (item, index) {
673
+ var formKey = getFormKey(control.controlRef.concat(index));
674
+ var valid = acc[formKey] === undefined ? form[formKey].valid : acc[formKey].valid;
675
+ return valid;
676
+ });
677
+ }
678
+ else if (control.config.controls) {
679
+ // If control is a FormGroup
680
+ childrenValid = Object.keys(control.value).every(function (childKey) {
681
+ var formKey = getFormKey(control.controlRef.concat(childKey));
682
+ var valid = acc[formKey] === undefined ? form[formKey].valid : acc[formKey].valid;
683
+ return valid;
684
+ });
685
+ }
686
+ return __assign(__assign({}, acc), (_b = {}, _b[key] = __assign(__assign({}, control), { errors: errors, valid: selfValid && childrenValid }), _b));
630
687
  }, {});
631
- return childrenErrorsChecked;
688
+ return __assign(__assign({}, form), errorsMerged);
632
689
  };
633
690
 
634
691
  var isControlValidating = function (control) {
@@ -636,9 +693,6 @@ var isControlValidating = function (control) {
636
693
  return false;
637
694
  return Object.values(control.asyncValidateInProgress).some(function (pending) { return pending; });
638
695
  };
639
- var isControlAsyncValid = function (control) {
640
- return !Object.values(control.asyncValidatorErrors).some(function (error) { return error; });
641
- };
642
696
  var getControlByKey = function (key, form) {
643
697
  return Object.values(form).find(function (control) { return control.key === key; });
644
698
  };
@@ -656,15 +710,81 @@ var asyncValidationResponseSuccess = function (form, _a) {
656
710
  var key = _a[0], control = _a[1];
657
711
  if (ancestors.includes(control)) {
658
712
  var descendants = getDescendantControls(control.controlRef, controlUpdated);
659
- return __assign(__assign({}, acc), (_b = {}, _b[key] = __assign(__assign({}, control), { pending: descendants.some(function (control) { return isControlValidating(control); }), asyncValidatorsValid: descendants.every(function (control) { return isControlAsyncValid(control); }) }), _b));
713
+ return __assign(__assign({}, acc), (_b = {}, _b[key] = __assign(__assign({}, control), { pending: descendants.some(function (control) { return isControlValidating(control); }) }), _b));
660
714
  }
661
715
  return __assign(__assign({}, acc), (_c = {}, _c[key] = control, _c));
662
716
  }, {});
663
- return mergeErrors(ancestorsUpdated);
717
+ return mergeBranchErrors(ancestorsUpdated, control.controlRef);
718
+ };
719
+
720
+ var hasErrors = function (errors) {
721
+ return Object.values(errors).some(function (hasError) { return hasError; });
722
+ };
723
+ // TODO: update merge errors to not do the entire form but just a subset of it
724
+ // TODO: separation of concern to update validity of control and ancestors
725
+ var mergeErrors = function (form) {
726
+ var errorsMerged = Object.entries(form)
727
+ .reverse()
728
+ .reduce(function (acc, _a) {
729
+ var _b;
730
+ var key = _a[0], control = _a[1];
731
+ var errors = __assign(__assign({}, control.validatorErrors), control.asyncValidatorErrors);
732
+ var selfValid = !hasErrors(errors);
733
+ var childrenValid = true;
734
+ if (Array.isArray(control.config.controls)) {
735
+ // If control is a FormArray
736
+ childrenValid = control.value.every(function (item, index) { return acc[getFormKey(control.controlRef.concat(index))].valid; });
737
+ }
738
+ else if (control.config.controls) {
739
+ // If control is a FormGroup
740
+ childrenValid = Object.keys(control.value).every(function (childKey) { return acc[getFormKey(control.controlRef.concat(childKey))].valid; });
741
+ }
742
+ return __assign(__assign({}, acc), (_b = {}, _b[key] = __assign(__assign({}, control), { errors: errors, valid: selfValid && childrenValid }), _b));
743
+ }, {});
744
+ var restoredOrder = Object.keys(errorsMerged)
745
+ .reverse()
746
+ .reduce(function (acc, key) {
747
+ acc[key] = errorsMerged[key];
748
+ return acc;
749
+ }, {});
750
+ return restoredOrder;
751
+ };
752
+
753
+ var mergeValueUpdated = function (state, form, controlRef) {
754
+ var controlBranch = getControlBranch(controlRef, form).reduce(function (acc, control) {
755
+ var _a;
756
+ var key = getFormKey(control.controlRef);
757
+ return __assign(__assign({}, acc), (_a = {}, _a[key] = __assign(__assign({}, state[key]), control), _a));
758
+ }, {});
759
+ return mergeBranchErrors(__assign(__assign({}, state), controlBranch), controlRef);
760
+ };
761
+
762
+ var mergeRemoveControl = function (state, form, controlRef) {
763
+ var parentRef = controlRef.slice(0, -1);
764
+ var controlBranch = getControlBranch(parentRef, form).reduce(function (acc, baseControl) {
765
+ var _a;
766
+ var key = getFormKey(baseControl.controlRef);
767
+ var existingControl = getControlBranch(parentRef, state).find(function (control) { return baseControl.key === control.key; });
768
+ return __assign(__assign({}, acc), (_a = {}, _a[key] = __assign(__assign({}, existingControl), baseControl), _a));
769
+ }, {});
770
+ var removedControls = __assign({}, state);
771
+ var descendants = getDescendantControls(parentRef, state);
772
+ descendants.forEach(function (control) {
773
+ delete removedControls[getFormKey(control.controlRef)];
774
+ });
775
+ return mergeBranchErrors(__assign(__assign({}, removedControls), controlBranch), parentRef);
776
+ };
777
+
778
+ var mergeTouchUpdated = function (state, form, controlRef) {
779
+ var controlBranch = getControlBranch(controlRef, form).reduce(function (acc, control) {
780
+ var _a;
781
+ var key = getFormKey(control.controlRef);
782
+ return __assign(__assign({}, acc), (_a = {}, _a[key] = __assign(__assign({}, state[key]), control), _a));
783
+ }, {});
784
+ return __assign(__assign({}, state), controlBranch);
664
785
  };
665
786
 
666
787
  var DEFAULT_HUB2_FIELDS = {
667
- asyncValidatorsValid: true,
668
788
  asyncValidatorErrors: {},
669
789
  asyncValidateInProgress: {},
670
790
  pending: false,
@@ -674,16 +794,37 @@ var DEFAULT_HUB2_FIELDS = {
674
794
  var formChange = function (state, _a) {
675
795
  if (state === void 0) { state = null; }
676
796
  var _b = _a.payload, form = _b.form, action = _b.action;
677
- return mergeErrors(Object.entries(form).reduce(function (acc, _a) {
678
- var _b;
679
- var dictKey = _a[0], baseControl = _a[1];
680
- var existingControl = (action === null || action === void 0 ? void 0 : action.type) === 'removeControl'
681
- ? state && Object.values(state).find(function (control) { return baseControl.key === control.key; })
682
- : state && state[dictKey];
683
- return __assign(__assign({}, acc), (_b = {}, _b[dictKey] = __assign(__assign({}, (existingControl
684
- ? existingControl
685
- : structuredClone(DEFAULT_HUB2_FIELDS))), baseControl), _b));
686
- }, {}));
797
+ if (state === null) {
798
+ return mergeErrors(Object.entries(form).reduce(function (acc, _a) {
799
+ var _b;
800
+ var dictKey = _a[0], baseControl = _a[1];
801
+ return __assign(__assign({}, acc), (_b = {}, _b[dictKey] = __assign(__assign({}, structuredClone(DEFAULT_HUB2_FIELDS)), baseControl), _b));
802
+ }, {}));
803
+ }
804
+ switch (action === null || action === void 0 ? void 0 : action.type) {
805
+ case 'updateValues':
806
+ case 'addControl':
807
+ return mergeValueUpdated(state, form, action.payload.controlRef);
808
+ case 'resetControl':
809
+ case 'removeControl':
810
+ return mergeRemoveControl(state, form, action.payload);
811
+ case 'markControlAsPristine':
812
+ case 'markControlAsUntouched':
813
+ return mergeTouchUpdated(state, form, action.payload);
814
+ case 'markControlAsTouched':
815
+ return mergeTouchUpdated(state, form, action.payload.controlRef);
816
+ default:
817
+ return mergeErrors(Object.entries(form).reduce(function (acc, _a) {
818
+ var _b;
819
+ var dictKey = _a[0], baseControl = _a[1];
820
+ var existingControl = (action === null || action === void 0 ? void 0 : action.type) === 'removeControl'
821
+ ? state && Object.values(state).find(function (control) { return baseControl.key === control.key; })
822
+ : state && state[dictKey];
823
+ return __assign(__assign({}, acc), (_b = {}, _b[dictKey] = __assign(__assign({}, (existingControl
824
+ ? existingControl
825
+ : structuredClone(DEFAULT_HUB2_FIELDS))), baseControl), _b));
826
+ }, {}));
827
+ }
687
828
  };
688
829
 
689
830
  var control = function (config) {
@@ -741,17 +882,12 @@ var RxForm = {
741
882
  };
742
883
 
743
884
  var getArrayItems = function (controlRef, form) {
744
- if (!Array.isArray(getControl(controlRef, form).config.controls)) {
885
+ var control = getControl(controlRef, form);
886
+ if (!Array.isArray(control.config.controls)) {
745
887
  throw "".concat(controlRef.join('.'), " is not a Form Array control");
746
888
  }
747
- return Object.values(form)
748
- .filter(function (control) {
749
- var isItem = controlRef.every(function (key, index) { return key === control.controlRef[index]; }) &&
750
- control.controlRef.length === controlRef.length + 1 &&
751
- typeof control.controlRef[controlRef.length] === 'number';
752
- return isItem;
753
- })
754
- .sort(function (a, b) { return +a.controlRef.slice(-1) - +b.controlRef.slice(-1); });
889
+ var result = control.value.map(function (_, index) { return form[getFormKey(controlRef.concat(index))]; });
890
+ return result;
755
891
  };
756
892
 
757
893
  exports.ControlModels = Controls;
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.3-alpha.1",
17
+ "@reactables/core": "^0.4.5-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.3-alpha.1"
24
+ "version": "0.4.5-alpha.0"
25
25
  }
@@ -1,2 +0,0 @@
1
- import { BaseForm } from '../../Models/Controls';
2
- export declare const updateDirty: <T>(form: BaseForm<T>) => BaseForm<T>;
@@ -1 +0,0 @@
1
- export {};