@reactables/forms 0.6.0-alpha.0 → 0.7.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.
package/README.md CHANGED
@@ -1,25 +1,33 @@
1
- # Reactable Forms (WIP)
1
+ # Reactable Forms
2
2
 
3
3
  ## Description
4
4
 
5
- State Management of reactive forms with [Reactables](https://github.com/reactables/reactables/tree/main/packages/core).
5
+ Reactive forms with [Reactables](https://github.com/reactables/reactables/tree/main/packages/core).
6
6
 
7
7
  ## Table of Contents
8
8
 
9
9
  1. [Installation](#installation)
10
- 1. [Examples](#examples)
11
- 1. [Form Control](#form-control)
12
- 1. [Form Array](#form-array)
13
- 1. [Form Group](#form-group)
14
-
15
10
  1. [API](#api)
16
11
  1. [RxActions](#api-actions)
12
+ 1. [updateValues](#api-actions-update-values)
13
+ 1. [addControl](#api-actions-add-conrtrol)
14
+ 1. [pushControl](#api-actions-push-control)
15
+ 1. [removeControl](#api-actions-remove-control)
16
+ 1. [markControlAsPristine](#api-actions-mark-as-pristine)
17
+ 1. [markControlAsTouched](#api-actions-mark-as-touched)
18
+ 1. [markControlAsUntouched](#api-actions-mark-as-untouched)
19
+ 1. [resetControl](#api-actions-resetControl)
17
20
  1. [build](#api-build)
21
+ 1. [RxFormOptions](#api-form-options)
18
22
  1. [control](#api-control)
19
23
  1. [group](#api-group)
20
24
  1. [array](#api-array)
21
- 1. [Other Interfaces](#interfaces)
22
- 1. [EffectsAndSources](#effects-sources)
25
+ 1. [Other Interfaces](#api-interfaces)
26
+ 1. [Form](#api-form)
27
+ 1. [FormControl](#api-form-control)
28
+ 1. [ControlRef](#api-control-ref)
29
+ 1. [FormErrors](#api-form-errors)
30
+ 1. [FormReducers](#api-form-reducers)
23
31
 
24
32
 
25
33
  ## Installation <a name="installation"></a>
@@ -28,10 +36,6 @@ Installation will require [RxJS](https://rxjs.dev/) if not already installed.
28
36
 
29
37
  `npm i rxjs @reactables/forms`
30
38
 
31
- ## Examples <a name="examples"></a>
32
-
33
- WIP
34
-
35
39
  ## API <a name="api"></a>
36
40
 
37
41
  The API for building Reactable Forms is very similar to [Angular FormBuilder](https://angular.io/api/forms/FormBuilder). It has been adapted to support Reactable features.
@@ -40,28 +44,130 @@ The API for building Reactable Forms is very similar to [Angular FormBuilder](ht
40
44
 
41
45
  Actions available to trigger state changes on Reactable.
42
46
 
47
+ #### `updateValues` <a name="api-actions-update-values"></a>
48
+
49
+ Updates value of a [`FormControl`](#api-form-control). For form group and form arrays, update will only occur if specified descendant controls exists. Otherwise it will throw an error.
50
+
51
+ ```typescript
52
+ type updateValues = <T>(payload: UpdateValuesPayload<T>) => void;
53
+
54
+ export interface UpdateValuesPayload<T> {
55
+ value: T;
56
+ controlRef: ControlRef;
57
+ }
58
+
59
+ ```
60
+
61
+ #### `addControl` <a name="api-actions-add-control"></a>
62
+
63
+ Adds a control to a form group.
64
+
65
+ ```typescript
66
+ type addControl = (payload: AddControlPayload) => void;
67
+
68
+ export interface AddControlPayload {
69
+ config: AbstractControlConfig;
70
+ controlRef: ControlRef;
71
+ }
72
+
73
+ ```
74
+
75
+ #### `pushControl` <a name="api-actions-push-control"></a>
76
+
77
+ Pushes a control to a form array.
78
+
79
+ ```typescript
80
+ type pushControl = (payload: PushControlPayload) => void;
81
+
82
+ export interface PushControlPayload {
83
+ config: AbstractControlConfig;
84
+ controlRef: ControlRef;
85
+ }
86
+
87
+ ```
88
+
89
+ #### `removeControl` <a name="api-actions-remove-control"></a>
90
+
91
+ Removes a specified control from form.
92
+
93
+ ```typescript
94
+ type removeControl = (payload: ControlRef) => void;
95
+
96
+ ```
97
+
98
+ #### `markControlAsPristine` <a name="api-actions-mark-as-pristine"></a>
99
+
100
+ Marks a control and all descendant controls as pristine.
101
+
102
+ ```typescript
103
+ type markControlAsPristine = (payload: ControlRef) => void;
104
+
105
+ ```
106
+
107
+ #### `markControlAsTouched` <a name="api-actions-mark-as-touched"></a>
108
+
109
+ Marks a control and all ancestors as touched. Can pass a `markAll` true to mark all descendants as touched as well.
110
+
111
+ ```typescript
112
+ type markControlAsTouched = (payload: MarkTouchedPayload) => void;
113
+
114
+ export interface MarkTouchedPayload {
115
+ controlRef: ControlRef;
116
+ markAll?: boolean;
117
+ }
118
+
119
+ ```
120
+
121
+ #### `markControlAsUntouched` <a name="api-actions-mark-as-untouched"></a>
122
+
123
+ Marks a control and all descendants as untouched. Will recheck ancestors controls and update touched status.
124
+
125
+ ```typescript
126
+ type markControlAsUnTouched = (payload: ControlRef) => void;
127
+
128
+ ```
129
+
130
+ #### `resetControl` <a name="api-actions-resetControl"></a>
131
+
132
+ Marks a control and all descendants as untouched. Will recheck ancestors controls and update touched status.
133
+
43
134
  ```typescript
44
- type RxFormActions = {
45
- updateValues: <T>(payload: ControlChange<T>) => void;
46
- addControl: (payload: AddControl) => void;
47
- pushControl: (payload: PushControl) => void;
48
- removeControl: (payload: ControlRef) => void;
49
- markControlAsPristine: (payload: ControlRef) => void;
50
- markControlAsTouched: (payload: MarkTouched) => void;
51
- markControlAsUntouched: (payload: ControlRef) => void;
52
- resetControl: (payload: ControlRef) => void;
53
- };
135
+ type resetControls = (payload: ControlRef) => void;
136
+
54
137
  ```
55
138
 
56
139
  ### `build` <a name="api-build"></a>
57
140
 
58
141
  ```typescript
59
- type build = (config: AbstractControlConfig, options?: EffectsAndSources) => Reactable<Form<unknown>, RxFormActions>
142
+ type build = (config: AbstractControlConfig, options?: RxFormOptions) => Reactable<Form<unknown>, RxFormActions>
60
143
  ```
61
144
 
62
- Factory method for creating a form Reactable. Accepts a configuration object generated by one or more helper methods - [`control`](#api-control), [`group`](#api-group), [`array`](#api-array).
145
+ Factory method for creating a form Reactable. Accepts a configuration object generated by one or more helper methods - [`control`](#api-control), [`group`](#api-group), [`array`](#api-array). Also accepts an `RxFormOptions` object.
146
+
147
+
148
+ #### `RxFormOptions` <a name="api-form-options"></a>
149
+
150
+ Options to customize RxForm behaviour.
63
151
 
64
- Options can also be provided to declare [Effects and Sources](#effects-sources) for the form Reactable.
152
+ ```typescript
153
+ interface RxFormOptions {
154
+ reducers?: { [key:string]: CustomReducer }
155
+ effects?: Effect<unknown, unknown>[];
156
+ sources?: Observable<Action<unknown>>[] | { [key: string]: Observable<unknown> };
157
+ }
158
+
159
+ type CustomReducer = (
160
+ reducers: FormReducers,
161
+ state: BaseFormState<unknown>,
162
+ action: Action<unknown>,
163
+ ) => BaseFormState<unknown>;
164
+
165
+ ```
166
+ | Property | Description |
167
+ | -------- | ----------- |
168
+ | reducers (optional) | Dictionary of `CustomReducer`s to implement custom form behaviour. The `CustomReducer` provides built in [`FormReducers`](#api-form-reducers). **Form state updates need to be made with [`FormReducers`](#api-form-reducers) to maintain integrity of the form state tree (i.e validation states of parent and child controls)**. |
169
+ | effects (optional) | Array of [Effects](https://github.com/reactables/reactables/tree/main/packages/core#api-effect) to be registered to the Reactable. |
170
+ | sources (optional) | Additional [Action](https://github.com/reactables/reactables/tree/main/packages/core#action-) Observables the Reactable is listening to. Can be an array or a dictionary where key is the action type and value is the Observable emitting the payload. |
65
171
 
66
172
  ### `control` <a name="api-control"></a>
67
173
 
@@ -105,16 +211,85 @@ interface FormArrayConfig {
105
211
  }
106
212
  ```
107
213
 
108
- ### Other Interfaces <a name="interfaces"></a>
214
+ ### Other Interfaces <a name="api-interfaces"></a>
215
+
216
+ #### `Form` <a name="api-form"></a>
217
+ Form state. Dictionary of [`FormControl`](#api-form-control)(s) where the key is a period separated representation of the [`ControlRef`](#api-control-ref) tuple.
109
218
 
110
- #### EffectsAndSources <a name="effects-sources"></a>
111
219
  ```typescript
112
- interface EffectsAndSources {
113
- effects?: Effect<unknown, unknown>[];
114
- sources?: Observable<Action<unknown>>[] | { [key: string]: Observable<unknown> };
220
+ export interface Form<T> {
221
+ root?: FormControl<T>;
222
+ [key: string]: FormControl<unknown>;
223
+ }
224
+
225
+ ```
226
+
227
+ #### `FormControl` <a name="api-form-control"></a>
228
+
229
+ ```typescript
230
+
231
+ export interface FormControl<T> extends BaseControl<T>, Hub2Fields {
232
+ pristineValue: T;
233
+ controlRef: ControlRef;
234
+ value: T;
235
+ dirty: boolean;
236
+ touched: boolean;
237
+ validatorErrors: FormErrors;
238
+ key: string;
239
+ asyncValidatorErrors: FormErrors;
240
+ asyncValidateInProgress: { [key: string | number]: boolean };
241
+ errors: FormErrors;
242
+ valid: boolean;
243
+ childrenValid: boolean;
244
+ pending?: boolean;
245
+ config: AbstractControlConfig;
115
246
  }
116
247
  ```
117
248
  | Property | Description |
118
249
  | -------- | ----------- |
119
- | effects (optional) | Array of [Effects](https://github.com/reactables/reactables/tree/main/packages/core#api-effect) to be registered to the Reactable |
120
- | sources (optional) | Additional [Action](https://github.com/reactables/reactables/tree/main/packages/core#action-) Observables the Reactable is listening to. Can be an array or a dictionary where key is the action type and value is the Observable emitting the payload |
250
+ | pristineValue | Original value of control. Use to determine if control is dirty. |
251
+ | controlRef | Controls [`ControlRef`](#api-control-ref). |
252
+ | value | Control value. |
253
+ | touched | Touched status of control |
254
+ | validatorErrors | [`FormErrors`](#api-form-errors) from validators (non-async) |
255
+ | asyncValidatorErrors | [`FormErrors`](#api-form-errors) from async validators |
256
+ | errors | [`FormErrors`](#api-form-errors) validatorErrors and asyncValidatorErrors merged. |
257
+ | valid | Valid status of control. Also checks descendants.
258
+ | childrenValid | Valid status of direct child controls.
259
+ | config | Original config for form control |
260
+
261
+
262
+
263
+ #### `ControlRef` <a name="api-control-ref"></a>
264
+
265
+ Control Reference represented as a tuple for the [`FormControl`](#api-form-control)
266
+
267
+ #### `FormErrors` <a name="api-form-errors"></a>
268
+
269
+ Dictionary of errors for the control.
270
+
271
+ ```typescript
272
+ export interface FormErrors {
273
+ [key: string]: boolean;
274
+ }
275
+ ```
276
+
277
+ #### `FormReducers` <a name="api-form-reducers"></a>
278
+
279
+ Built in reducers to be used to update state of form tree. Payload and behaviour is same and descrbed in [`RxActions`](#api-actions);
280
+
281
+ ```typescript
282
+
283
+ export interface FormReducers {
284
+ updateValues: <T>(state: BaseFormState<T>, payload: UpdateValuesPayload<unknown>,
285
+ ) => BaseFormState<T>;
286
+ removeControl: <T>(state: BaseFormState<T>, payload: ControlRef) => BaseFormState<T>;
287
+ pushControl: <T>(state: BaseFormState<T>, payload: PushControlPayload) => BaseFormState<T>;
288
+ addControl: <T>(state: BaseFormState<T>, payload: AddControlPayload) => BaseFormState<T>;
289
+ markControlAsPristine: <T>(state: BaseFormState<T>, payload: ControlRef) => BaseFormState<T>;
290
+ markControlAsTouched: <T>(state: BaseFormState<T>, payload: MarkTouchedPayload) => BaseFormState<T>;
291
+ markControlAsUntouched: <T>(state: BaseFormState<T>, payload: ControlRef,
292
+ ) => BaseFormState<T>;
293
+ resetControl: <T>(state: BaseFormState<T>, payload: ControlRef) => BaseFormState<T>;
294
+ }
295
+ ```
@@ -1,4 +1,4 @@
1
1
  import { Observable } from 'rxjs';
2
- import { Action, Reactable } from '@reactables/core';
2
+ import { Action } from '@reactables/core';
3
3
  import { BaseFormState } from '../Models/Controls';
4
- export declare const buildHub2Source: <T, S>(rx: Reactable<BaseFormState<T>, S>) => Observable<Action<T>>;
4
+ export declare const buildHub2Source: <T, S>(hub1State$: Observable<BaseFormState<T>>) => Observable<Action<T>>;
@@ -13,6 +13,7 @@ export interface FormArrayConfig extends ValidatorConfigs {
13
13
  }
14
14
  export interface FormControlConfig<T> extends ValidatorConfigs {
15
15
  initialValue: T;
16
+ normalizers?: ((value: T) => T)[];
16
17
  }
17
18
  export type AbstractControlConfig = (FormControlConfig<unknown> | FormArrayConfig | FormGroupConfig) & {
18
19
  controls?: AbstractControlConfig[] | {
@@ -1,15 +1,15 @@
1
1
  import { ControlRef } from './ControlRef';
2
2
  import { AbstractControlConfig } from './Configs';
3
3
  import { FormErrors } from './FormErrors';
4
- export interface ControlChange<T> {
4
+ export interface UpdateValuesPayload<T> {
5
5
  value: T;
6
6
  controlRef: ControlRef;
7
7
  }
8
- export interface AddControl {
8
+ export interface AddControlPayload {
9
9
  config: AbstractControlConfig;
10
10
  controlRef: ControlRef;
11
11
  }
12
- export interface PushControl {
12
+ export interface PushControlPayload {
13
13
  config: AbstractControlConfig;
14
14
  controlRef: ControlRef;
15
15
  }
@@ -18,7 +18,7 @@ export interface ControlAsyncValidationResponse {
18
18
  validatorIndex: number;
19
19
  errors: FormErrors;
20
20
  }
21
- export interface MarkTouched {
21
+ export interface MarkTouchedPayload {
22
22
  controlRef: ControlRef;
23
23
  markAll?: boolean;
24
24
  }
@@ -2,5 +2,5 @@ export { AbstractControlConfig, FormArrayConfig, FormGroupConfig, FormControlCon
2
2
  export { ControlRef } from './ControlRef';
3
3
  export * as ControlModels from './Controls';
4
4
  export { FormErrors } from './FormErrors';
5
- export { ControlChange, AddControl, ControlAsyncValidationResponse, MarkTouched } from './Payloads';
5
+ export { UpdateValuesPayload, AddControlPayload, ControlAsyncValidationResponse, MarkTouchedPayload, } from './Payloads';
6
6
  export { ValidatorAsyncFn, ValidatorFn } from './Validators';
@@ -1,4 +1,4 @@
1
1
  import { Action } from '@reactables/core';
2
2
  import { BaseFormState } from '../../Models/Controls';
3
- import { AddControl } from '../../Models/Payloads';
4
- export declare const addControl: <T>(state: BaseFormState<T>, action: Action<AddControl>, mergeChanges?: boolean) => BaseFormState<T>;
3
+ import { AddControlPayload } from '../../Models/Payloads';
4
+ export declare const addControl: <T>(state: BaseFormState<T>, action: Action<AddControlPayload>, mergeChanges?: boolean) => BaseFormState<T>;
@@ -1,4 +1,4 @@
1
1
  import { Action } from '@reactables/core';
2
2
  import { BaseFormState } from '../../Models/Controls';
3
- import { MarkTouched } from '../../Models/Payloads';
4
- export declare const markControlAsTouched: <T>(state: BaseFormState<T>, action: Action<MarkTouched>, mergeChanges?: boolean) => BaseFormState<T>;
3
+ import { MarkTouchedPayload } from '../../Models/Payloads';
4
+ export declare const markControlAsTouched: <T>(state: BaseFormState<T>, action: Action<MarkTouchedPayload>, mergeChanges?: boolean) => BaseFormState<T>;
@@ -1,4 +1,4 @@
1
1
  import { Action } from '@reactables/core';
2
2
  import { BaseFormState } from '../../Models/Controls';
3
- import { AddControl } from '../../Models/Payloads';
4
- export declare const pushControl: <T>(state: BaseFormState<T>, action: Action<AddControl>, mergeChanges?: boolean) => BaseFormState<T>;
3
+ import { AddControlPayload } from '../../Models/Payloads';
4
+ export declare const pushControl: <T>(state: BaseFormState<T>, action: Action<AddControlPayload>, mergeChanges?: boolean) => BaseFormState<T>;
@@ -1,5 +1,5 @@
1
1
  import { Action } from '@reactables/core';
2
2
  import { BaseForm } from '../../Models/Controls';
3
- import { ControlChange } from '../../Models/Payloads';
3
+ import { UpdateValuesPayload } 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, value } }: Action<ControlChange<unknown>>) => BaseForm<T>;
5
+ export declare const updateAncestorValues: <T>(form: BaseForm<T>, { payload: { controlRef, value } }: Action<UpdateValuesPayload<unknown>>) => BaseForm<T>;
@@ -1,5 +1,5 @@
1
1
  import { Action } from '@reactables/core';
2
2
  import { BaseForm } from '../../Models/Controls';
3
- import { ControlChange } from '../../Models/Payloads';
3
+ import { UpdateValuesPayload } from '../../Models/Payloads';
4
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>;
5
+ export declare const updateAncestorValuesAddControl: <T>(form: BaseForm<T>, { payload: { controlRef, value } }: Action<UpdateValuesPayload<unknown>>) => BaseForm<T>;
@@ -1,4 +1,4 @@
1
1
  import { Action } from '@reactables/core';
2
2
  import { BaseFormState } from '../../Models/Controls';
3
- import { ControlChange } from '../../Models/Payloads';
4
- export declare const updateValues: <T>({ form, changedControls, removedControls }: BaseFormState<T>, action: Action<ControlChange<unknown>>, mergeChanges?: boolean) => BaseFormState<T>;
3
+ import { UpdateValuesPayload } from '../../Models/Payloads';
4
+ export declare const updateValues: <T>({ form, changedControls, removedControls }: BaseFormState<T>, action: Action<UpdateValuesPayload<unknown>>, mergeChanges?: boolean) => BaseFormState<T>;
@@ -1,5 +1,5 @@
1
- import { Reactable, EffectsAndSources, Action } from '@reactables/core';
2
- import { ControlChange, AddControl, MarkTouched, PushControl } from '../Models/Payloads';
1
+ import { Reactable, EffectsAndSources, Action, Effect, ScopedEffects } from '@reactables/core';
2
+ import { UpdateValuesPayload, AddControlPayload, MarkTouchedPayload, PushControlPayload } 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';
@@ -9,27 +9,31 @@ export declare const control: <T>(config: FormControlConfig<T> | FbControl<T>) =
9
9
  export declare const array: (config: FormArrayConfig) => FormArrayConfig;
10
10
  export declare const group: (config: FormGroupConfig) => FormGroupConfig;
11
11
  export type RxFormActions = {
12
- updateValues: <T>(payload: ControlChange<T>) => void;
13
- addControl: (payload: AddControl) => void;
14
- pushControl: (payload: PushControl) => void;
12
+ updateValues: <T>(payload: UpdateValuesPayload<T>) => void;
13
+ addControl: (payload: AddControlPayload) => void;
14
+ pushControl: (payload: PushControlPayload) => void;
15
15
  removeControl: (payload: ControlRef) => void;
16
16
  markControlAsPristine: (payload: ControlRef) => void;
17
- markControlAsTouched: (payload: MarkTouched) => void;
17
+ markControlAsTouched: (payload: MarkTouchedPayload) => void;
18
18
  markControlAsUntouched: (payload: ControlRef) => void;
19
19
  resetControl: (payload: ControlRef) => void;
20
20
  };
21
21
  export interface FormReducers {
22
- updateValues: <T>(state: BaseFormState<T>, action: Action<ControlChange<unknown>>) => BaseFormState<T>;
23
- removeControl: <T>(state: BaseFormState<T>, action: Action<ControlRef>) => BaseFormState<T>;
24
- pushControl: <T>(state: BaseFormState<T>, action: Action<PushControl>) => BaseFormState<T>;
25
- addControl: <T>(state: BaseFormState<T>, action: Action<AddControl>) => BaseFormState<T>;
26
- markControlAsPristine: <T>(state: BaseFormState<T>, action: Action<ControlRef>) => BaseFormState<T>;
27
- markControlAsTouched: <T>(state: BaseFormState<T>, action: Action<MarkTouched>) => BaseFormState<T>;
28
- markControlAsUntouched: <T>(state: BaseFormState<T>, action: Action<ControlRef>) => BaseFormState<T>;
29
- resetControl: <T>(state: BaseFormState<T>, action: Action<ControlRef>) => BaseFormState<T>;
22
+ updateValues: <T>(state: BaseFormState<T>, payload: UpdateValuesPayload<unknown>) => BaseFormState<T>;
23
+ removeControl: <T>(state: BaseFormState<T>, payload: ControlRef) => BaseFormState<T>;
24
+ pushControl: <T>(state: BaseFormState<T>, payload: PushControlPayload) => BaseFormState<T>;
25
+ addControl: <T>(state: BaseFormState<T>, payload: AddControlPayload) => BaseFormState<T>;
26
+ markControlAsPristine: <T>(state: BaseFormState<T>, payload: ControlRef) => BaseFormState<T>;
27
+ markControlAsTouched: <T>(state: BaseFormState<T>, payload: MarkTouchedPayload) => BaseFormState<T>;
28
+ markControlAsUntouched: <T>(state: BaseFormState<T>, payload: ControlRef) => BaseFormState<T>;
29
+ resetControl: <T>(state: BaseFormState<T>, payload: ControlRef) => BaseFormState<T>;
30
30
  }
31
+ type CustomReducer = (reducers: FormReducers, state: BaseFormState<unknown>, action: Action<unknown>) => BaseFormState<unknown>;
31
32
  export interface CustomReducers {
32
- [key: string]: (reducers: FormReducers, state: BaseFormState<unknown>, action: Action<unknown>) => BaseFormState<unknown>;
33
+ [key: string]: CustomReducer | {
34
+ reducer: CustomReducer;
35
+ effects?: ((payload?: unknown) => ScopedEffects<unknown>) | Effect<unknown, unknown>[];
36
+ };
33
37
  }
34
38
  export interface RxFormOptions<T extends CustomReducers> extends EffectsAndSources {
35
39
  reducers?: T;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.js CHANGED
@@ -221,8 +221,8 @@ var getAsyncValidationActions = function (formControls) {
221
221
  }, []);
222
222
  };
223
223
 
224
- var buildHub2Source = function (rx) {
225
- var hub1StateMapped$ = rx.state$.pipe(operators.map(function (payload) { return ({ type: 'formChange', payload: payload }); }));
224
+ var buildHub2Source = function (hub1State$) {
225
+ var hub1StateMapped$ = hub1State$.pipe(operators.map(function (payload) { return ({ type: 'formChange', payload: payload }); }));
226
226
  var sourceForHub2$ = hub1StateMapped$.pipe(operators.mergeMap(function (formChangeAction) {
227
227
  var changedControls = formChangeAction.payload.changedControls;
228
228
  var controlsToCheck = changedControls ? Object.values(changedControls) : [];
@@ -351,7 +351,7 @@ var updateDescendants = function (state, _a) {
351
351
  };
352
352
  };
353
353
  // Will only update child controls that are present.
354
- // Use AddControl/RemoveControl action reducers to add/remove control
354
+ // Use AddControlPayload/RemoveControl action reducers to add/remove control
355
355
  var updateValues = function (_a, action, mergeChanges) {
356
356
  var _b, _c;
357
357
  var form = _a.form, _d = _a.changedControls, changedControls = _d === void 0 ? {} : _d, _e = _a.removedControls, removedControls = _e === void 0 ? {} : _e;
@@ -359,20 +359,25 @@ var updateValues = function (_a, action, mergeChanges) {
359
359
  var _f = action.payload, controlRef = _f.controlRef, value = _f.value;
360
360
  // Update its own value
361
361
  var ctrlKey = getFormKey(controlRef);
362
- var validatorErrors = getErrors(form[ctrlKey], value);
363
- var newControl = __assign(__assign({}, form[ctrlKey]), { validatorErrors: validatorErrors, dirty: !isEqual__default["default"](value, form[ctrlKey].pristineValue), value: value });
362
+ var newValue = value;
363
+ var config = form[ctrlKey].config;
364
+ if (config.normalizers) {
365
+ newValue = config.normalizers.reduce(function (acc, normalizer) { return normalizer(acc); }, value);
366
+ }
367
+ var validatorErrors = getErrors(form[ctrlKey], newValue);
368
+ var newControl = __assign(__assign({}, form[ctrlKey]), { validatorErrors: validatorErrors, dirty: !isEqual__default["default"](value, form[ctrlKey].pristineValue), value: newValue });
364
369
  var result = {
365
370
  form: __assign(__assign({}, form), (_b = {}, _b[ctrlKey] = newControl, _b)),
366
371
  changedControls: (_c = {}, _c[newControl.key] = newControl, _c)
367
372
  };
368
- var configControls = form[ctrlKey].config.controls;
373
+ var configControls = config.controls;
369
374
  // Update its children
370
375
  if (configControls) {
371
376
  result = updateDescendants(result, {
372
377
  type: UPDATE_DESCENDANT_VALUES,
373
378
  payload: {
374
379
  controlRef: controlRef,
375
- value: value
380
+ value: newValue
376
381
  }
377
382
  });
378
383
  }
@@ -380,7 +385,7 @@ var updateValues = function (_a, action, mergeChanges) {
380
385
  if (controlRef.length) {
381
386
  result = __assign(__assign({}, result), { form: updateAncestorValues(result.form, {
382
387
  type: UPDATE_ANCESTOR_VALUES,
383
- payload: { controlRef: controlRef, value: value }
388
+ payload: { controlRef: controlRef, value: newValue }
384
389
  }) });
385
390
  }
386
391
  var changedAncestorControls = getAncestorControls(controlRef, result.form).reduce(function (acc, control) {
@@ -989,29 +994,29 @@ var control = function (config) {
989
994
  var array = function (config) { return config; };
990
995
  var group = function (config) { return config; };
991
996
  var reducerTools = {
992
- updateValues: function (state, action) {
993
- return updateValues(state, action, true);
997
+ updateValues: function (state, payload) {
998
+ return updateValues(state, { payload: payload }, true);
994
999
  },
995
- removeControl: function (state, action) {
996
- return removeControl(state, action, true);
1000
+ removeControl: function (state, payload) {
1001
+ return removeControl(state, { payload: payload }, true);
997
1002
  },
998
- pushControl: function (state, action) {
999
- return pushControl(state, action, true);
1003
+ pushControl: function (state, payload) {
1004
+ return pushControl(state, { payload: payload }, true);
1000
1005
  },
1001
- addControl: function (state, action) {
1002
- return addControl(state, action, true);
1006
+ addControl: function (state, payload) {
1007
+ return addControl(state, { payload: payload }, true);
1003
1008
  },
1004
- markControlAsPristine: function (state, action) {
1005
- return markControlAsPristine(state, action, true);
1009
+ markControlAsPristine: function (state, payload) {
1010
+ return markControlAsPristine(state, { payload: payload }, true);
1006
1011
  },
1007
- markControlAsTouched: function (state, action) {
1008
- return markControlAsTouched(state, action, true);
1012
+ markControlAsTouched: function (state, payload) {
1013
+ return markControlAsTouched(state, { payload: payload }, true);
1009
1014
  },
1010
- markControlAsUntouched: function (state, action) {
1011
- return markControlAsUntouched(state, action, true);
1015
+ markControlAsUntouched: function (state, payload) {
1016
+ return markControlAsUntouched(state, { payload: payload }, true);
1012
1017
  },
1013
- resetControl: function (state, action) {
1014
- return resetControl(state, action, true);
1018
+ resetControl: function (state, payload) {
1019
+ return resetControl(state, { payload: payload }, true);
1015
1020
  }
1016
1021
  };
1017
1022
  var build = function (config, options) {
@@ -1020,15 +1025,20 @@ var build = function (config, options) {
1020
1025
  var reducers = options.reducers, otherOptions = __rest(options, ["reducers"]);
1021
1026
  var customReducers = Object.entries(reducers || {}).reduce(function (acc, _a) {
1022
1027
  var _b;
1023
- var key = _a[0], reducer = _a[1];
1024
- return (__assign(__assign({}, acc), (_b = {}, _b[key] = function (_a, action) {
1025
- var form = _a.form;
1026
- return reducer(reducerTools, { form: form }, action);
1027
- }, _b)));
1028
+ var key = _a[0], _case = _a[1];
1029
+ var _reducer = typeof _case === 'function' ? _case : _case.reducer;
1030
+ var effects = typeof _case === 'function' ? [] : _case.effects;
1031
+ return __assign(__assign({}, acc), (_b = {}, _b[key] = {
1032
+ reducer: function (_a, action) {
1033
+ var form = _a.form;
1034
+ return _reducer(reducerTools, { form: form }, action);
1035
+ },
1036
+ effects: effects
1037
+ }, _b));
1028
1038
  }, {});
1029
- var rxHub1 = core.RxBuilder(__assign({ initialState: initialState, reducers: __assign({ updateValues: updateValues, removeControl: removeControl, addControl: addControl, pushControl: pushControl, markControlAsPristine: markControlAsPristine, markControlAsTouched: markControlAsTouched, markControlAsUntouched: markControlAsUntouched, resetControl: resetControl }, customReducers) }, otherOptions));
1030
- var rxHub2 = core.RxBuilder({
1031
- sources: [buildHub2Source(rxHub1)],
1039
+ var _a = core.RxBuilder(__assign({ initialState: initialState, reducers: __assign({ updateValues: updateValues, removeControl: removeControl, addControl: addControl, pushControl: pushControl, markControlAsPristine: markControlAsPristine, markControlAsTouched: markControlAsTouched, markControlAsUntouched: markControlAsUntouched, resetControl: resetControl }, customReducers) }, otherOptions)), hub1State$ = _a[0], hub1Actions = _a[1];
1040
+ var state$ = core.RxBuilder({
1041
+ sources: [buildHub2Source(hub1State$)],
1032
1042
  initialState: null,
1033
1043
  reducers: {
1034
1044
  formChange: formChange,
@@ -1041,11 +1051,11 @@ var build = function (config, options) {
1041
1051
  },
1042
1052
  asyncValidationResponseSuccess: asyncValidationResponseSuccess
1043
1053
  }
1044
- });
1045
- return {
1046
- state$: rxHub2.state$.pipe(operators.filter(function (form) { return form !== null; })),
1047
- actions: rxHub1.actions
1048
- };
1054
+ })[0];
1055
+ return [
1056
+ state$.pipe(operators.filter(function (form) { return form !== null; })),
1057
+ hub1Actions,
1058
+ ];
1049
1059
  };
1050
1060
 
1051
1061
  var getArrayItems = function (controlRef, form) {
package/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "author": "David Lai",
15
15
  "license": "ISC",
16
16
  "dependencies": {
17
- "@reactables/core": "^0.6.0-alpha.0",
17
+ "@reactables/core": "^0.7.0-alpha.0",
18
18
  "lodash.isequal": "^4.5.0"
19
19
  },
20
20
  "peerDependencies": {
@@ -23,5 +23,5 @@
23
23
  "devDependencies": {
24
24
  "lodash.clonedeep": "^4.5.0"
25
25
  },
26
- "version": "0.6.0-alpha.0"
26
+ "version": "0.7.0-alpha.0"
27
27
  }