@reactables/forms 1.0.0-beta.6 → 1.0.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 +326 -21
- package/dist/Helpers/controlRefCheck.d.ts +5 -0
- package/dist/Helpers/controlRefCheck.test.d.ts +1 -0
- package/dist/Helpers/index.d.ts +2 -0
- package/dist/Models/Controls.d.ts +2 -2
- package/dist/Reducers/Hub1/updateValues.d.ts +1 -1
- package/dist/Reducers/Hub2/mergeControls.d.ts +1 -1
- package/dist/RxForm/RxForm.d.ts +4 -4
- package/dist/index.js +92 -42
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -7,6 +7,13 @@ Reactive forms with [Reactables](https://github.com/reactables/reactables/tree/m
|
|
|
7
7
|
## Table of Contents
|
|
8
8
|
|
|
9
9
|
1. [Installation](#installation)
|
|
10
|
+
1. [Examples](#examples)
|
|
11
|
+
1. [Basic Form Group](#basic-form-group)
|
|
12
|
+
1. [Validation](#validation-example)
|
|
13
|
+
1. [Async Validation](#async-validation-example)
|
|
14
|
+
1. [Normalizing Values](#normalizing-values)
|
|
15
|
+
1. [Custom Reducer](#custom-reducer-example)
|
|
16
|
+
|
|
10
17
|
1. [API](#api)
|
|
11
18
|
1. [RxActions](#api-actions)
|
|
12
19
|
1. [updateValues](#api-actions-update-values)
|
|
@@ -27,18 +34,254 @@ Reactive forms with [Reactables](https://github.com/reactables/reactables/tree/m
|
|
|
27
34
|
1. [FormControl](#api-form-control)
|
|
28
35
|
1. [ControlRef](#api-control-ref)
|
|
29
36
|
1. [FormErrors](#api-form-errors)
|
|
37
|
+
1. [ValidatorFn](#api-validator-fn)
|
|
38
|
+
1. [ValidatorAsyncFn](#api-validator-fn-async)
|
|
30
39
|
1. [FormReducers](#api-form-reducers)
|
|
40
|
+
1. [CustomReducers](#api-custom-reducers)
|
|
41
|
+
1. [BaseFormState](#api-base-form-state)
|
|
42
|
+
1. [BaseControl](#api-base-control)
|
|
31
43
|
|
|
32
44
|
|
|
33
45
|
## Installation <a name="installation"></a>
|
|
34
46
|
|
|
35
47
|
Installation requires [RxJS](https://rxjs.dev/) to be present.
|
|
36
48
|
|
|
37
|
-
`npm i rxjs
|
|
49
|
+
`npm i rxjs` (if not already installed)
|
|
50
|
+
|
|
51
|
+
`npm i @reactables/forms`
|
|
52
|
+
|
|
53
|
+
## Examples <a name="examples"></a>
|
|
54
|
+
|
|
55
|
+
### Basic Form Group <a name="basic-form-group"></a>
|
|
56
|
+
|
|
57
|
+
[See full example on StackBlitz](https://stackblitz.com/edit/github-qtpo1k-vm45ed?file=src%2Findex.js)
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import { control, build, group } from '@reactables/forms';
|
|
61
|
+
|
|
62
|
+
const [state$, actions] = build(
|
|
63
|
+
group({
|
|
64
|
+
controls: {
|
|
65
|
+
name: control(['']),
|
|
66
|
+
},
|
|
67
|
+
})
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
// Cache the DOM
|
|
71
|
+
const nameControlEl = document.getElementById('name-control');
|
|
72
|
+
|
|
73
|
+
// Bind Event Handlers
|
|
74
|
+
nameControlEl.oninput = ({ target: { value } }) => {
|
|
75
|
+
actions.updateValues({
|
|
76
|
+
controlRef: ['name'],
|
|
77
|
+
value,
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
nameControlEl.onblur = () => {
|
|
82
|
+
actions.markControlAsTouched({ controlRef: ['name'] });
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// Subscribe to state updates and bind to view.
|
|
86
|
+
state$.subscribe((state) => {
|
|
87
|
+
const { name } = state;
|
|
88
|
+
|
|
89
|
+
nameControlEl.value = name.value;
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Validation <a name="validation-example"></a>
|
|
95
|
+
|
|
96
|
+
`@reactable/forms` only comes with 3 built in validators, `required`, `email` & `arrayNotEmpty`. The developer can implement their own `ValidatorFn`s and provide them when building the reactable.
|
|
97
|
+
|
|
98
|
+
[See full example on StackBlitz](https://stackblitz.com/edit/github-qtpo1k-f6tz82?file=src%2Findex.js)
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
import { control, build, group } from '@reactables/forms';
|
|
102
|
+
|
|
103
|
+
// Create Reactable
|
|
104
|
+
const rxForm = build(
|
|
105
|
+
group({
|
|
106
|
+
controls: {
|
|
107
|
+
donuts: control(['0', ['required', 'min4']]),
|
|
108
|
+
},
|
|
109
|
+
}),
|
|
110
|
+
{
|
|
111
|
+
providers: {
|
|
112
|
+
validators: {
|
|
113
|
+
min4: (value) => ({ min4: Number(value) < 4 }),
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
const [state$, actions] = rxForm;
|
|
120
|
+
|
|
121
|
+
// ...Cache the DOM and bind event handlers
|
|
122
|
+
|
|
123
|
+
// Subscribe to state updates and bind to view.
|
|
124
|
+
state$.subscribe((state) => {
|
|
125
|
+
const { donuts } = state;
|
|
126
|
+
|
|
127
|
+
donutControlEl.value = donuts.value;
|
|
128
|
+
|
|
129
|
+
const handleErrors = (el, show) => {
|
|
130
|
+
el.className = show ? 'form-error show' : 'form-error';
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
handleErrors(donuntMinOrderErrorEl, donuts.touched && donuts.errors.min4);
|
|
134
|
+
handleErrors(donuntRequiredErrorEl, donuts.touched && donuts.errors.required);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Async Validation <a name="async-validation-example"></a>
|
|
142
|
+
|
|
143
|
+
`FormControl`s have a `pending: boolean` state when their value changes and are awaiting the result from asynchronous validation.
|
|
144
|
+
|
|
145
|
+
[See full example on StackBlitz](https://stackblitz.com/edit/github-qtpo1k-wvznqm?file=src%2Findex.js)
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
import { control, build, group } from '@reactables/forms';
|
|
149
|
+
import { of, switchMap, delay } from 'rxjs';
|
|
150
|
+
|
|
151
|
+
const [state$, actions] = build(
|
|
152
|
+
group({
|
|
153
|
+
controls: {
|
|
154
|
+
email: control(['', ['required', 'email'], ['blacklistedEmail']]),
|
|
155
|
+
},
|
|
156
|
+
}),
|
|
157
|
+
{
|
|
158
|
+
providers: {
|
|
159
|
+
asyncValidators: {
|
|
160
|
+
blacklistedEmail: (control$) =>
|
|
161
|
+
control$.pipe(
|
|
162
|
+
switchMap(({ value }) =>
|
|
163
|
+
of({
|
|
164
|
+
blacklistedEmail: value === 'already@taken.com',
|
|
165
|
+
}).pipe(delay(1000))
|
|
166
|
+
)
|
|
167
|
+
),
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
// ...Bind Event Handlers
|
|
174
|
+
|
|
175
|
+
// Subscribe to state updates and bind to view.
|
|
176
|
+
state$.subscribe((state) => {
|
|
177
|
+
const { email } = state;
|
|
178
|
+
|
|
179
|
+
emailControlEl.value = email.value;
|
|
180
|
+
|
|
181
|
+
const handleErrors = (el, show) => {
|
|
182
|
+
el.className = show ? 'form-error show' : 'form-error';
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
emailPendingEl.className = email.pending ? 'show' : '';
|
|
186
|
+
|
|
187
|
+
handleErrors(emailRequiredErrorEl, email.touched && email.errors.required);
|
|
188
|
+
handleErrors(emailAsyncErrorEl, email.errors.blacklistedEmail);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Normalize Values <a name="normalizing-values"></a>
|
|
195
|
+
|
|
196
|
+
User input for a `FormControl` leaf (i.e having no child controls) can be normalized via normalizer functions provided during form initialization.
|
|
197
|
+
|
|
198
|
+
[See full example on StackBlitz](https://stackblitz.com/edit/github-qtpo1k-frpncu?file=src%2findex.js)
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
import { control, build, group } from '@reactables/forms';
|
|
202
|
+
|
|
203
|
+
export const normalizePhone = (value) => {
|
|
204
|
+
let input = value.replace(/\D/g, '').substring(0, 10); // First ten digits of input only
|
|
205
|
+
const areaCode = input.substring(0, 3);
|
|
206
|
+
const middle = input.substring(3, 6);
|
|
207
|
+
const last = input.substring(6, 10);
|
|
208
|
+
|
|
209
|
+
if (input.length > 6) {
|
|
210
|
+
input = `(${areaCode}) ${middle} - ${last}`;
|
|
211
|
+
} else if (input.length > 3) {
|
|
212
|
+
input = `(${areaCode}) ${middle}`;
|
|
213
|
+
} else if (input.length > 0) {
|
|
214
|
+
input = `(${areaCode}`;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return input;
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
const rxForm = build(
|
|
221
|
+
group({
|
|
222
|
+
controls: {
|
|
223
|
+
phone: control({
|
|
224
|
+
initialValue: '',
|
|
225
|
+
normalizers: ['phone']
|
|
226
|
+
}),
|
|
227
|
+
},
|
|
228
|
+
}),
|
|
229
|
+
{
|
|
230
|
+
providers: {
|
|
231
|
+
normalizers: {
|
|
232
|
+
phone: normalizePhone,
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
}
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
// ... Bind event handlers and view
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Custom Reducer <a name="custom-reducer-example"></a>
|
|
242
|
+
|
|
243
|
+
You can declare [`CustomReducer`s](#api-custom-reducers) during form initialization to implement custom behaviour.
|
|
244
|
+
|
|
245
|
+
Below the form reactable will have a `doubleOrder` action method which can be called to double the order amount.
|
|
246
|
+
|
|
247
|
+
[See full example on StackBlitz](https://stackblitz.com/edit/github-qtpo1k-3qppus?file=src%2Findex.js)
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
import { control, build, group } from '@reactables/forms';
|
|
251
|
+
|
|
252
|
+
const [state$, actions] = build(
|
|
253
|
+
group({
|
|
254
|
+
controls: {
|
|
255
|
+
donuts: control(['0', 'min4']),
|
|
256
|
+
},
|
|
257
|
+
}),
|
|
258
|
+
{
|
|
259
|
+
providers: {
|
|
260
|
+
validators: {
|
|
261
|
+
min4: (value) => ({ min4: Number(value) < 4 }),
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
reducers: {
|
|
265
|
+
doubleOrder: (formReducers, state) => {
|
|
266
|
+
/** Use built in Form Reducers for updating the form tree. **/
|
|
267
|
+
const { updateValues } = formReducers;
|
|
268
|
+
|
|
269
|
+
const orders = Number(state.form.donuts.value);
|
|
270
|
+
const value = (orders * 2).toString();
|
|
271
|
+
|
|
272
|
+
return updateValues(state, { controlRef: ['donuts'], value });
|
|
273
|
+
};,
|
|
274
|
+
},
|
|
275
|
+
}
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
// ... Bind event handlers and view
|
|
279
|
+
|
|
280
|
+
```
|
|
38
281
|
|
|
39
282
|
## API <a name="api"></a>
|
|
40
283
|
|
|
41
|
-
The API for building Reactable Forms
|
|
284
|
+
The API for building Reactable Forms inspired by [Angular FormBuilder](https://angular.io/api/forms/FormBuilder). It has been adapted to support Reactable features.
|
|
42
285
|
|
|
43
286
|
### `RxActions` <a name="api-actions"></a>
|
|
44
287
|
|
|
@@ -51,7 +294,7 @@ Updates values of a [`FormControl`](#api-form-control). For form group and form
|
|
|
51
294
|
```typescript
|
|
52
295
|
type updateValues = <T>(payload: UpdateValuesPayload<T>) => void;
|
|
53
296
|
|
|
54
|
-
|
|
297
|
+
interface UpdateValuesPayload<T> {
|
|
55
298
|
value: T;
|
|
56
299
|
controlRef: ControlRef;
|
|
57
300
|
}
|
|
@@ -65,7 +308,7 @@ Adds a control to a form group.
|
|
|
65
308
|
```typescript
|
|
66
309
|
type addControl = (payload: AddControlPayload) => void;
|
|
67
310
|
|
|
68
|
-
|
|
311
|
+
interface AddControlPayload {
|
|
69
312
|
config: AbstractControlConfig;
|
|
70
313
|
controlRef: ControlRef;
|
|
71
314
|
}
|
|
@@ -79,7 +322,7 @@ Pushes a control to a form array.
|
|
|
79
322
|
```typescript
|
|
80
323
|
type pushControl = (payload: PushControlPayload) => void;
|
|
81
324
|
|
|
82
|
-
|
|
325
|
+
interface PushControlPayload {
|
|
83
326
|
config: AbstractControlConfig;
|
|
84
327
|
controlRef: ControlRef;
|
|
85
328
|
}
|
|
@@ -106,12 +349,12 @@ type markControlAsPristine = (payload: ControlRef) => void;
|
|
|
106
349
|
|
|
107
350
|
#### `markControlAsTouched` <a name="api-actions-mark-as-touched"></a>
|
|
108
351
|
|
|
109
|
-
Marks a control and all ancestors as touched. Can set `markAll` to `true` to mark all descendants as touched as well.
|
|
352
|
+
Marks a control and all ancestors as touched. Can set `markAll` to `true` to mark all descendants as touched as well (defaults to `false`).
|
|
110
353
|
|
|
111
354
|
```typescript
|
|
112
355
|
type markControlAsTouched = (payload: MarkTouchedPayload) => void;
|
|
113
356
|
|
|
114
|
-
|
|
357
|
+
interface MarkTouchedPayload {
|
|
115
358
|
controlRef: ControlRef;
|
|
116
359
|
markAll?: boolean;
|
|
117
360
|
}
|
|
@@ -129,7 +372,7 @@ type markControlAsUnTouched = (payload: ControlRef) => void;
|
|
|
129
372
|
|
|
130
373
|
#### `resetControl` <a name="api-actions-resetControl"></a>
|
|
131
374
|
|
|
132
|
-
|
|
375
|
+
Resets a control by removing existing control and rebuilding it with the original configuration.
|
|
133
376
|
|
|
134
377
|
```typescript
|
|
135
378
|
type resetControls = (payload: ControlRef) => void;
|
|
@@ -155,17 +398,10 @@ interface RxFormOptions {
|
|
|
155
398
|
effects?: Effect<unknown, unknown>[];
|
|
156
399
|
sources?: Observable<Action<unknown>>[] | { [key: string]: Observable<unknown> };
|
|
157
400
|
}
|
|
158
|
-
|
|
159
|
-
type CustomReducer = (
|
|
160
|
-
reducers: FormReducers,
|
|
161
|
-
state: BaseFormState<unknown>,
|
|
162
|
-
action: Action<unknown>,
|
|
163
|
-
) => BaseFormState<unknown>;
|
|
164
|
-
|
|
165
401
|
```
|
|
166
402
|
| Property | Description |
|
|
167
403
|
| -------- | ----------- |
|
|
168
|
-
| reducers (optional) | Dictionary of `CustomReducer`s to implement custom form behaviour. The `
|
|
404
|
+
| reducers (optional) | Dictionary of [`CustomReducer`s](#api-custom-reducers) to implement custom form behaviour. The `CustomReducerFunc`(#api-custom-reducers) 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
405
|
| effects (optional) | Array of [Effects](https://github.com/reactables/reactables/tree/main/packages/core#api-effect) to be registered to the Reactable. |
|
|
170
406
|
| 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. |
|
|
171
407
|
|
|
@@ -217,7 +453,7 @@ interface FormArrayConfig {
|
|
|
217
453
|
Form state. Dictionary of [`FormControl`](#api-form-control)(s) where the key is a period separated representation of the [`ControlRef`](#api-control-ref) tuple.
|
|
218
454
|
|
|
219
455
|
```typescript
|
|
220
|
-
|
|
456
|
+
interface Form<T> {
|
|
221
457
|
root?: FormControl<T>;
|
|
222
458
|
[key: string]: FormControl<unknown>;
|
|
223
459
|
}
|
|
@@ -228,7 +464,7 @@ export interface Form<T> {
|
|
|
228
464
|
|
|
229
465
|
```typescript
|
|
230
466
|
|
|
231
|
-
|
|
467
|
+
interface FormControl<T> {
|
|
232
468
|
pristineValue: T;
|
|
233
469
|
controlRef: ControlRef;
|
|
234
470
|
value: T;
|
|
@@ -269,18 +505,36 @@ Control Reference represented as a tuple for the [`FormControl`](#api-form-contr
|
|
|
269
505
|
Dictionary of errors for the control.
|
|
270
506
|
|
|
271
507
|
```typescript
|
|
272
|
-
|
|
508
|
+
interface FormErrors {
|
|
273
509
|
[key: string]: boolean;
|
|
274
510
|
}
|
|
275
511
|
```
|
|
276
512
|
|
|
513
|
+
#### `ValidatorFn` <a name="api-validator-fn"></a>
|
|
514
|
+
|
|
515
|
+
Validator function that reads the value of the `FormControl` and returns a `FormErrors` object.
|
|
516
|
+
|
|
517
|
+
```typescript
|
|
518
|
+
type ValidatorFn = (value: unknown) => FormErrors
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
#### `ValidatorFnAsync` <a name="api-validator-fn-async"></a>
|
|
522
|
+
|
|
523
|
+
Validator function takes in an `BaseControl` observable and returns an `Observable<FormErrors>`.
|
|
524
|
+
|
|
525
|
+
```typescript
|
|
526
|
+
type ValidatorAsyncFn = <T>(control$: Observable<BaseControl<T>>) => Observable<FormErrors>;
|
|
527
|
+
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
|
|
277
531
|
#### `FormReducers` <a name="api-form-reducers"></a>
|
|
278
532
|
|
|
279
|
-
Built in reducers which can be used to update the state of the form tree. Payload and behaviour is the same and
|
|
533
|
+
Built in reducers which can be used to update the state of the form tree. Payload and behaviour is the same and described in [`RxActions`](#api-actions);
|
|
280
534
|
|
|
281
535
|
```typescript
|
|
282
536
|
|
|
283
|
-
|
|
537
|
+
interface FormReducers {
|
|
284
538
|
updateValues: <T>(state: BaseFormState<T>, payload: UpdateValuesPayload<unknown>,
|
|
285
539
|
) => BaseFormState<T>;
|
|
286
540
|
removeControl: <T>(state: BaseFormState<T>, payload: ControlRef) => BaseFormState<T>;
|
|
@@ -292,4 +546,55 @@ export interface FormReducers {
|
|
|
292
546
|
) => BaseFormState<T>;
|
|
293
547
|
resetControl: <T>(state: BaseFormState<T>, payload: ControlRef) => BaseFormState<T>;
|
|
294
548
|
}
|
|
549
|
+
```
|
|
550
|
+
#### `CustomReducers` <a name="api-custom-reducers"></a>
|
|
551
|
+
|
|
552
|
+
```typescript
|
|
553
|
+
type CustomReducerFunc = (
|
|
554
|
+
reducers: FormReducers,
|
|
555
|
+
state: BaseFormState<unknown>,
|
|
556
|
+
action: Action<unknown>,
|
|
557
|
+
) => BaseFormState<unknown>;
|
|
558
|
+
|
|
559
|
+
type CustomReducer =
|
|
560
|
+
| CustomReducerFunc
|
|
561
|
+
| {
|
|
562
|
+
reducer: CustomReducerFunc;
|
|
563
|
+
effects?: Effect<unknown, unknown>[] | ((payload?: unknown) => ScopedEffects<unknown>);
|
|
564
|
+
};
|
|
565
|
+
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
#### `BaseFormState` <a name="api-base-form-state"></a>
|
|
569
|
+
|
|
570
|
+
Form state before it is fully validated. This is accessible in `CustomReducer`s so developer can read the current state and implement custom form behaviours.
|
|
571
|
+
|
|
572
|
+
```typescript
|
|
573
|
+
interface BaseFormState<T> {
|
|
574
|
+
form: BaseForm<T>;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
interface BaseForm<T> {
|
|
578
|
+
root?: BaseControl<T>;
|
|
579
|
+
[key: string]: BaseControl<unknown>;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
#### `BaseControl` <a name="api-base-control"></a>
|
|
585
|
+
|
|
586
|
+
`BaseControl` contains some control information before a fully validated `FormControl` is created.
|
|
587
|
+
|
|
588
|
+
```typescript
|
|
589
|
+
|
|
590
|
+
interface BaseControl<T> {
|
|
591
|
+
pristineValue: T;
|
|
592
|
+
controlRef: ControlRef;
|
|
593
|
+
value: T;
|
|
594
|
+
dirty: boolean;
|
|
595
|
+
touched: boolean;
|
|
596
|
+
validatorErrors: FormErrors;
|
|
597
|
+
config: AbstractControlConfig;
|
|
598
|
+
key: string;
|
|
599
|
+
}
|
|
295
600
|
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/Helpers/index.d.ts
CHANGED
|
@@ -29,10 +29,10 @@ export interface FormControl<T> extends BaseControl<T>, Hub2Fields {
|
|
|
29
29
|
}
|
|
30
30
|
export interface BaseFormState<T> {
|
|
31
31
|
form: BaseForm<T>;
|
|
32
|
-
|
|
32
|
+
_changedControls?: {
|
|
33
33
|
[key: string]: BaseControl<unknown>;
|
|
34
34
|
};
|
|
35
|
-
|
|
35
|
+
_removedConrols?: {
|
|
36
36
|
[key: string]: BaseControl<unknown>;
|
|
37
37
|
};
|
|
38
38
|
}
|
|
@@ -2,4 +2,4 @@ import { Action } from '@reactables/core';
|
|
|
2
2
|
import { BaseFormState } from '../../Models/Controls';
|
|
3
3
|
import { UpdateValuesPayload } from '../../Models/Payloads';
|
|
4
4
|
import { RxFormProviders } from '../../RxForm/RxForm';
|
|
5
|
-
export declare const updateValues: <T>({ form,
|
|
5
|
+
export declare const updateValues: <T>({ form, _changedControls, _removedConrols }: BaseFormState<T>, action: Action<UpdateValuesPayload<unknown>>, providers: RxFormProviders, mergeChanges?: boolean) => BaseFormState<T>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Form, FormControl, BaseFormState } from '../../Models/Controls';
|
|
2
|
-
export declare const mergeControls: <T>(state: Form<T>, { form,
|
|
2
|
+
export declare const mergeControls: <T>(state: Form<T>, { form, _changedControls, _removedConrols }: BaseFormState<unknown>) => {
|
|
3
3
|
[x: string]: FormControl<unknown>;
|
|
4
4
|
root?: FormControl<unknown>;
|
|
5
5
|
};
|
package/dist/RxForm/RxForm.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export type RxFormActions = {
|
|
|
17
17
|
markControlAsTouched: (payload: MarkTouchedPayload) => void;
|
|
18
18
|
markControlAsUntouched: (payload: ControlRef) => void;
|
|
19
19
|
resetControl: (payload: ControlRef) => void;
|
|
20
|
-
};
|
|
20
|
+
} & ActionMap;
|
|
21
21
|
export interface FormReducers {
|
|
22
22
|
updateValues: <T>(state: BaseFormState<T>, payload: UpdateValuesPayload<unknown>) => BaseFormState<T>;
|
|
23
23
|
removeControl: <T>(state: BaseFormState<T>, payload: ControlRef) => BaseFormState<T>;
|
|
@@ -31,7 +31,7 @@ export interface FormReducers {
|
|
|
31
31
|
export type CustomReducerFunc = (reducers: FormReducers, state: BaseFormState<unknown>, action: Action<unknown>) => BaseFormState<unknown>;
|
|
32
32
|
export type CustomReducer = CustomReducerFunc | {
|
|
33
33
|
reducer: CustomReducerFunc;
|
|
34
|
-
effects?: ((payload?: unknown) => ScopedEffects<unknown>)
|
|
34
|
+
effects?: Effect<unknown, unknown>[] | ((payload?: unknown) => ScopedEffects<unknown>);
|
|
35
35
|
};
|
|
36
36
|
export type CustomReducers<T> = {
|
|
37
37
|
[key in keyof (T & {
|
|
@@ -57,6 +57,6 @@ export interface RxFormProviders {
|
|
|
57
57
|
[key: string]: ValidatorAsyncFn;
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
|
-
export declare const build: (config: AbstractControlConfig, options?: RxFormOptions) => Reactable<Form<unknown>,
|
|
61
|
-
export declare const load: (state: Form<unknown>, options?: RxFormOptions) => Reactable<Form<unknown>,
|
|
60
|
+
export declare const build: (config: AbstractControlConfig, options?: RxFormOptions) => Reactable<Form<unknown>, RxFormActions>;
|
|
61
|
+
export declare const load: (state: Form<unknown>, options?: RxFormOptions) => Reactable<Form<unknown>, RxFormActions>;
|
|
62
62
|
export {};
|
package/dist/index.js
CHANGED
|
@@ -240,8 +240,8 @@ var getAsyncValidationActions = function (formControls) {
|
|
|
240
240
|
var buildHub2Source = function (hub1State$) {
|
|
241
241
|
var hub1StateMapped$ = hub1State$.pipe(operators.map(function (payload) { return ({ type: 'formChange', payload: payload }); }));
|
|
242
242
|
var sourceForHub2$ = hub1StateMapped$.pipe(operators.mergeMap(function (formChangeAction) {
|
|
243
|
-
var
|
|
244
|
-
var controlsToCheck =
|
|
243
|
+
var _changedControls = formChangeAction.payload._changedControls;
|
|
244
|
+
var controlsToCheck = _changedControls ? Object.values(_changedControls) : [];
|
|
245
245
|
var asyncValidationActions = getAsyncValidationActions(controlsToCheck);
|
|
246
246
|
return rxjs.of.apply(void 0, __spreadArray([formChangeAction], asyncValidationActions, false));
|
|
247
247
|
}));
|
|
@@ -336,6 +336,46 @@ var getAncestorControls = function (controlRef, form, excludeSelf) {
|
|
|
336
336
|
});
|
|
337
337
|
};
|
|
338
338
|
|
|
339
|
+
/**
|
|
340
|
+
* @description see if any keys in a ControlRef has a "." probably a mistake by developer
|
|
341
|
+
*/
|
|
342
|
+
var controlRefCheck = function (ref) {
|
|
343
|
+
try {
|
|
344
|
+
var hasError = ref.some(function (key) {
|
|
345
|
+
if (typeof key === 'string') {
|
|
346
|
+
return key.includes('.');
|
|
347
|
+
}
|
|
348
|
+
return false;
|
|
349
|
+
});
|
|
350
|
+
if (hasError) {
|
|
351
|
+
var refString = "[".concat(ref.reduce(function (acc, key, index) {
|
|
352
|
+
if (index > 0) {
|
|
353
|
+
acc = acc.concat(', ');
|
|
354
|
+
}
|
|
355
|
+
if (typeof key === 'number') {
|
|
356
|
+
return acc.concat(key.toString());
|
|
357
|
+
}
|
|
358
|
+
return acc.concat("'".concat(key, "'"));
|
|
359
|
+
}, ''), "]");
|
|
360
|
+
var suggestion = "[".concat(ref.reduce(function (acc, key, index) {
|
|
361
|
+
if (index > 0) {
|
|
362
|
+
acc = acc.concat(', ');
|
|
363
|
+
}
|
|
364
|
+
if (typeof key === 'number') {
|
|
365
|
+
return acc.concat(key.toString());
|
|
366
|
+
}
|
|
367
|
+
var splitted = key
|
|
368
|
+
.split('.')
|
|
369
|
+
.map(function (key) { return "'".concat(key, "'"); })
|
|
370
|
+
.join(', ');
|
|
371
|
+
return acc.concat("".concat(splitted));
|
|
372
|
+
}, ''), "]");
|
|
373
|
+
console.warn("You provided ".concat(refString, ". Did you mean ").concat(suggestion, "?"));
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
catch (_a) { }
|
|
377
|
+
};
|
|
378
|
+
|
|
339
379
|
var UPDATE_DESCENDANT_VALUES = 'UPDATE_DESCENDANT_VALUES';
|
|
340
380
|
var updateDescendantValues = function (form, _a, providers) {
|
|
341
381
|
var _b = _a.payload, controlRef = _b.controlRef, value = _b.value;
|
|
@@ -364,10 +404,11 @@ var updateDescendantValues = function (form, _a, providers) {
|
|
|
364
404
|
// Use AddControlPayload/RemoveControl action reducers to add/remove control
|
|
365
405
|
var updateValues = function (_a, action, providers, mergeChanges) {
|
|
366
406
|
var _b, _c;
|
|
367
|
-
var form = _a.form, _d = _a.
|
|
407
|
+
var form = _a.form, _d = _a._changedControls, _changedControls = _d === void 0 ? {} : _d, _e = _a._removedConrols, _removedConrols = _e === void 0 ? {} : _e;
|
|
368
408
|
if (mergeChanges === void 0) { mergeChanges = false; }
|
|
369
409
|
var normalizers = providers.normalizers;
|
|
370
410
|
var _f = action.payload, controlRef = _f.controlRef, value = _f.value;
|
|
411
|
+
controlRefCheck(controlRef);
|
|
371
412
|
// Update its own value
|
|
372
413
|
var ctrlKey = getFormKey(controlRef);
|
|
373
414
|
var newValue = value;
|
|
@@ -384,7 +425,7 @@ var updateValues = function (_a, action, providers, mergeChanges) {
|
|
|
384
425
|
var newControl = __assign(__assign({}, form[ctrlKey]), { validatorErrors: validatorErrors, dirty: !isEqual__default["default"](value, form[ctrlKey].pristineValue), value: newValue });
|
|
385
426
|
var result = {
|
|
386
427
|
form: __assign(__assign({}, form), (_b = {}, _b[ctrlKey] = newControl, _b)),
|
|
387
|
-
|
|
428
|
+
_changedControls: (_c = {}, _c[newControl.key] = newControl, _c)
|
|
388
429
|
};
|
|
389
430
|
var configControls = config.controls;
|
|
390
431
|
// Update its descendants
|
|
@@ -400,7 +441,7 @@ var updateValues = function (_a, action, providers, mergeChanges) {
|
|
|
400
441
|
var _a;
|
|
401
442
|
return (__assign(__assign({}, acc), (_a = {}, _a[control.key] = control, _a)));
|
|
402
443
|
}, {});
|
|
403
|
-
result = __assign(__assign({}, result), { form: updatedDescendants,
|
|
444
|
+
result = __assign(__assign({}, result), { form: updatedDescendants, _changedControls: __assign(__assign({}, result._changedControls), changedDescendantControls) });
|
|
404
445
|
}
|
|
405
446
|
// Update its Ancestors
|
|
406
447
|
if (controlRef.length) {
|
|
@@ -413,7 +454,7 @@ var updateValues = function (_a, action, providers, mergeChanges) {
|
|
|
413
454
|
var _a;
|
|
414
455
|
return (__assign(__assign({}, acc), (_a = {}, _a[control.key] = control, _a)));
|
|
415
456
|
}, {});
|
|
416
|
-
var mergedResult = __assign(__assign({}, result), {
|
|
457
|
+
var mergedResult = __assign(__assign({}, result), { _changedControls: __assign(__assign(__assign({}, (mergeChanges ? _changedControls : undefined)), changedAncestorControls), result._changedControls), _removedConrols: mergeChanges ? _removedConrols : undefined });
|
|
417
458
|
return mergedResult;
|
|
418
459
|
};
|
|
419
460
|
|
|
@@ -450,6 +491,7 @@ var removeControl = function (state, action, providers, mergeChanges) {
|
|
|
450
491
|
if (mergeChanges === void 0) { mergeChanges = false; }
|
|
451
492
|
var form = state.form;
|
|
452
493
|
var controlRef = action.payload;
|
|
494
|
+
controlRefCheck(controlRef);
|
|
453
495
|
var controlToRemove = getControl(controlRef, form);
|
|
454
496
|
if (!controlToRemove) {
|
|
455
497
|
throw 'Control not found';
|
|
@@ -495,13 +537,13 @@ var removeControl = function (state, action, providers, mergeChanges) {
|
|
|
495
537
|
type: UPDATE_ANCESTOR_VALUES_REMOVE_CONTROL,
|
|
496
538
|
payload: controlRef
|
|
497
539
|
}, providers);
|
|
498
|
-
var
|
|
540
|
+
var _changedControls = __assign(__assign({}, (mergeChanges ? state._changedControls || {} : undefined)), getAncestorControls(controlRef.slice(0, -1), result).reduce(function (acc, control) {
|
|
499
541
|
var _a;
|
|
500
542
|
return (__assign(__assign({}, acc), (_a = {}, _a[control.key] = control, _a)));
|
|
501
543
|
}, {}));
|
|
502
544
|
// Check for reindexing for changed controls
|
|
503
545
|
if (parentIsFormArray) {
|
|
504
|
-
|
|
546
|
+
_changedControls = Object.entries(_changedControls).reduce(function (acc, _a) {
|
|
505
547
|
var _b, _c;
|
|
506
548
|
var key = _a[0], control = _a[1];
|
|
507
549
|
var oldIndex = control.controlRef.at(parentRef.length);
|
|
@@ -522,19 +564,19 @@ var removeControl = function (state, action, providers, mergeChanges) {
|
|
|
522
564
|
}
|
|
523
565
|
}, {});
|
|
524
566
|
}
|
|
525
|
-
var
|
|
567
|
+
var _removedConrols = __assign(__assign({}, (mergeChanges ? state._removedConrols || {} : undefined)), (_a = {}, _a[controlToRemove.key] = controlToRemove, _a));
|
|
526
568
|
descendants
|
|
527
569
|
.map(function (_a) {
|
|
528
570
|
var key = _a.key;
|
|
529
571
|
return key;
|
|
530
572
|
})
|
|
531
573
|
.forEach(function (key) {
|
|
532
|
-
delete
|
|
574
|
+
delete _changedControls[key];
|
|
533
575
|
});
|
|
534
576
|
return {
|
|
535
577
|
form: result,
|
|
536
|
-
|
|
537
|
-
|
|
578
|
+
_changedControls: _changedControls,
|
|
579
|
+
_removedConrols: _removedConrols
|
|
538
580
|
};
|
|
539
581
|
};
|
|
540
582
|
|
|
@@ -574,6 +616,7 @@ var getControlBranch = function (controlRef, form) {
|
|
|
574
616
|
var addControl = function (state, action, providers, mergeChanges) {
|
|
575
617
|
if (mergeChanges === void 0) { mergeChanges = false; }
|
|
576
618
|
var _a = action.payload, config = _a.config, controlRef = _a.controlRef;
|
|
619
|
+
controlRefCheck(controlRef);
|
|
577
620
|
// If controlRef does not exist we are adding control to a Form Group
|
|
578
621
|
if (!getControl(controlRef.slice(0, -1), state.form)) {
|
|
579
622
|
throw 'You are attempting to add a control to a non-existent form group';
|
|
@@ -584,14 +627,14 @@ var addControl = function (state, action, providers, mergeChanges) {
|
|
|
584
627
|
type: UPDATE_ANCESTOR_VALUES_ADD_CONTROL,
|
|
585
628
|
payload: { controlRef: controlRef, value: newValue }
|
|
586
629
|
}, providers);
|
|
587
|
-
var
|
|
630
|
+
var _changedControls = getControlBranch(controlRef, ancestorsUpdated).reduce(function (acc, control) {
|
|
588
631
|
var _a;
|
|
589
632
|
return (__assign(__assign({}, acc), (_a = {}, _a[control.key] = control, _a)));
|
|
590
633
|
}, {});
|
|
591
634
|
return {
|
|
592
635
|
form: ancestorsUpdated,
|
|
593
|
-
|
|
594
|
-
|
|
636
|
+
_changedControls: __assign(__assign({}, (mergeChanges ? state._changedControls || {} : undefined)), _changedControls),
|
|
637
|
+
_removedConrols: mergeChanges ? state._removedConrols || {} : undefined
|
|
595
638
|
};
|
|
596
639
|
};
|
|
597
640
|
|
|
@@ -599,6 +642,7 @@ var pushControl = function (state, action, providers, mergeChanges) {
|
|
|
599
642
|
if (mergeChanges === void 0) { mergeChanges = false; }
|
|
600
643
|
var newControlRef;
|
|
601
644
|
var _a = action.payload, config = _a.config, controlRef = _a.controlRef;
|
|
645
|
+
controlRefCheck(controlRef);
|
|
602
646
|
var existingControl = getControl(controlRef, state.form);
|
|
603
647
|
if (!existingControl)
|
|
604
648
|
throw 'You are attempting to push to a control that does not exist';
|
|
@@ -615,14 +659,14 @@ var pushControl = function (state, action, providers, mergeChanges) {
|
|
|
615
659
|
type: UPDATE_ANCESTOR_VALUES_ADD_CONTROL,
|
|
616
660
|
payload: { controlRef: newControlRef, value: newValue }
|
|
617
661
|
}, providers);
|
|
618
|
-
var
|
|
662
|
+
var _changedControls = getControlBranch(newControlRef, ancestorsUpdated).reduce(function (acc, control) {
|
|
619
663
|
var _a;
|
|
620
664
|
return (__assign(__assign({}, acc), (_a = {}, _a[control.key] = control, _a)));
|
|
621
665
|
}, {});
|
|
622
666
|
return {
|
|
623
667
|
form: ancestorsUpdated,
|
|
624
|
-
|
|
625
|
-
|
|
668
|
+
_changedControls: __assign(__assign({}, (mergeChanges ? state._changedControls || {} : undefined)), _changedControls),
|
|
669
|
+
_removedConrols: mergeChanges ? state._removedConrols || {} : undefined
|
|
626
670
|
};
|
|
627
671
|
};
|
|
628
672
|
|
|
@@ -666,6 +710,7 @@ var markControlAsPristine = function (state, action, mergeChanges) {
|
|
|
666
710
|
if (mergeChanges === void 0) { mergeChanges = false; }
|
|
667
711
|
var form = state.form;
|
|
668
712
|
var controlRef = action.payload;
|
|
713
|
+
controlRefCheck(controlRef);
|
|
669
714
|
var descendants = getDescendantControls(controlRef, form).reduce(function (acc, control) {
|
|
670
715
|
var _a;
|
|
671
716
|
return (__assign(__assign({}, acc), (_a = {}, _a[getFormKey(control.controlRef)] = __assign(__assign({}, control), { dirty: false, pristineValue: control.value }), _a)));
|
|
@@ -677,21 +722,22 @@ var markControlAsPristine = function (state, action, mergeChanges) {
|
|
|
677
722
|
payload: controlRef
|
|
678
723
|
});
|
|
679
724
|
}
|
|
680
|
-
var
|
|
725
|
+
var _changedControls = getControlBranch(controlRef, result).reduce(function (acc, control) {
|
|
681
726
|
var _a;
|
|
682
727
|
return (__assign(__assign({}, acc), (_a = {}, _a[control.key] = control, _a)));
|
|
683
728
|
}, {});
|
|
684
729
|
return {
|
|
685
730
|
form: result,
|
|
686
|
-
|
|
687
|
-
|
|
731
|
+
_changedControls: __assign(__assign({}, (mergeChanges ? state._changedControls || {} : undefined)), _changedControls),
|
|
732
|
+
_removedConrols: mergeChanges ? state._removedConrols || {} : undefined
|
|
688
733
|
};
|
|
689
734
|
};
|
|
690
735
|
|
|
691
736
|
var markControlAsTouched = function (state, action, mergeChanges) {
|
|
692
737
|
if (mergeChanges === void 0) { mergeChanges = false; }
|
|
693
738
|
var form = state.form;
|
|
694
|
-
var _a = action.payload, controlRef = _a.controlRef,
|
|
739
|
+
var _a = action.payload, controlRef = _a.controlRef, _b = _a.markAll, markAll = _b === void 0 ? false : _b;
|
|
740
|
+
controlRefCheck(controlRef);
|
|
695
741
|
var controls = (markAll ? getControlBranch(controlRef, form) : getAncestorControls(controlRef, form)).reduce(function (acc, control) {
|
|
696
742
|
var _a;
|
|
697
743
|
return (__assign(__assign({}, acc), (_a = {}, _a[getFormKey(control.controlRef)] = __assign(__assign({}, control), { touched: true }), _a)));
|
|
@@ -700,14 +746,14 @@ var markControlAsTouched = function (state, action, mergeChanges) {
|
|
|
700
746
|
form: __assign(__assign({}, form), controls),
|
|
701
747
|
action: action
|
|
702
748
|
};
|
|
703
|
-
var
|
|
749
|
+
var _changedControls = getControlBranch(controlRef, result.form).reduce(function (acc, control) {
|
|
704
750
|
var _a;
|
|
705
751
|
return (__assign(__assign({}, acc), (_a = {}, _a[control.key] = control, _a)));
|
|
706
752
|
}, {});
|
|
707
753
|
return {
|
|
708
754
|
form: __assign(__assign({}, form), controls),
|
|
709
|
-
|
|
710
|
-
|
|
755
|
+
_changedControls: __assign(__assign({}, (mergeChanges ? state._changedControls || {} : undefined)), _changedControls),
|
|
756
|
+
_removedConrols: mergeChanges ? state._removedConrols || {} : undefined
|
|
711
757
|
};
|
|
712
758
|
};
|
|
713
759
|
|
|
@@ -716,6 +762,7 @@ var markControlAsUntouched = function (state, action, mergeChanges) {
|
|
|
716
762
|
if (mergeChanges === void 0) { mergeChanges = false; }
|
|
717
763
|
var form = state.form;
|
|
718
764
|
var controlRef = action.payload;
|
|
765
|
+
controlRefCheck(controlRef);
|
|
719
766
|
var result = getDescendantControls(controlRef, form).reduce(function (acc, control) {
|
|
720
767
|
var _a;
|
|
721
768
|
return (__assign(__assign({}, acc), (_a = {}, _a[getFormKey(control.controlRef)] = __assign(__assign({}, control), { touched: false }), _a)));
|
|
@@ -729,14 +776,14 @@ var markControlAsUntouched = function (state, action, mergeChanges) {
|
|
|
729
776
|
key = getFormKey(currentRef);
|
|
730
777
|
result = __assign(__assign({}, result), (_a = {}, _a[key] = __assign(__assign({}, result[key]), { touched: getDescendantControls(currentRef, result, true).some(function (control) { return control.touched; }) }), _a));
|
|
731
778
|
}
|
|
732
|
-
var
|
|
779
|
+
var _changedControls = getControlBranch(controlRef, result).reduce(function (acc, control) {
|
|
733
780
|
var _a;
|
|
734
781
|
return (__assign(__assign({}, acc), (_a = {}, _a[control.key] = control, _a)));
|
|
735
782
|
}, {});
|
|
736
783
|
return {
|
|
737
784
|
form: result,
|
|
738
|
-
|
|
739
|
-
|
|
785
|
+
_changedControls: __assign(__assign({}, (mergeChanges ? state._changedControls || {} : undefined)), _changedControls),
|
|
786
|
+
_removedConrols: mergeChanges ? state._removedConrols || {} : undefined
|
|
740
787
|
};
|
|
741
788
|
};
|
|
742
789
|
|
|
@@ -745,6 +792,7 @@ var resetControl = function (state, action, providers, mergeChanges) {
|
|
|
745
792
|
if (mergeChanges === void 0) { mergeChanges = false; }
|
|
746
793
|
var form = state.form;
|
|
747
794
|
var controlRef = action.payload;
|
|
795
|
+
controlRefCheck(controlRef);
|
|
748
796
|
var controlToReset = getControl(controlRef, form);
|
|
749
797
|
var descendantsRemoved = __assign({}, form);
|
|
750
798
|
var descendants = getDescendantControls(controlRef, form);
|
|
@@ -762,24 +810,24 @@ var resetControl = function (state, action, providers, mergeChanges) {
|
|
|
762
810
|
type: UPDATE_ANCESTOR_VALUES,
|
|
763
811
|
payload: { controlRef: controlRef, value: restoredControlValue }
|
|
764
812
|
}, providers);
|
|
765
|
-
var
|
|
813
|
+
var _changedControls = __assign(__assign({}, (mergeChanges ? state._changedControls || {} : undefined)), getControlBranch(controlRef, result).reduce(function (acc, control) {
|
|
766
814
|
var _a;
|
|
767
815
|
return (__assign(__assign({}, acc), (_a = {}, _a[control.key] = control, _a)));
|
|
768
816
|
}, {}));
|
|
769
|
-
var
|
|
770
|
-
// If control is removed, we can delete it from the
|
|
817
|
+
var _removedConrols = __assign(__assign({}, (mergeChanges ? state._removedConrols || {} : undefined)), (_a = {}, _a[controlToReset.key] = controlToReset, _a));
|
|
818
|
+
// If control is removed, we can delete it from the _changedControls check
|
|
771
819
|
descendants
|
|
772
820
|
.map(function (_a) {
|
|
773
821
|
var key = _a.key;
|
|
774
822
|
return key;
|
|
775
823
|
})
|
|
776
824
|
.forEach(function (key) {
|
|
777
|
-
delete
|
|
825
|
+
delete _changedControls[key];
|
|
778
826
|
});
|
|
779
827
|
return {
|
|
780
828
|
form: result,
|
|
781
|
-
|
|
782
|
-
|
|
829
|
+
_changedControls: _changedControls,
|
|
830
|
+
_removedConrols: _removedConrols
|
|
783
831
|
};
|
|
784
832
|
};
|
|
785
833
|
|
|
@@ -937,26 +985,26 @@ var mergeRemoveControl = function (state, form, controlRef) {
|
|
|
937
985
|
}, {});
|
|
938
986
|
var updatedControlBranchOrderRestored = reverseObjectKeys(updatedControlBranch);
|
|
939
987
|
var descendants = existingBranch.filter(function (control) { return control.controlRef.length > parentRef.length; });
|
|
940
|
-
var
|
|
988
|
+
var _removedConrols = __assign({}, state);
|
|
941
989
|
descendants.forEach(function (control) {
|
|
942
|
-
delete
|
|
990
|
+
delete _removedConrols[getFormKey(control.controlRef)];
|
|
943
991
|
});
|
|
944
|
-
delete
|
|
945
|
-
return __assign(__assign({},
|
|
992
|
+
delete _removedConrols[getFormKey(controlRef)];
|
|
993
|
+
return __assign(__assign({}, _removedConrols), updatedControlBranchOrderRestored);
|
|
946
994
|
};
|
|
947
995
|
|
|
948
996
|
var hasErrors = function (errors) {
|
|
949
997
|
return Object.values(errors).some(function (hasError) { return hasError; });
|
|
950
998
|
};
|
|
951
999
|
var mergeControls = function (state, _a) {
|
|
952
|
-
var form = _a.form, _b = _a.
|
|
953
|
-
var controlsRemoved =
|
|
954
|
-
? Object.values(
|
|
1000
|
+
var form = _a.form, _b = _a._changedControls, _changedControls = _b === void 0 ? {} : _b, _removedConrols = _a._removedConrols;
|
|
1001
|
+
var controlsRemoved = _removedConrols
|
|
1002
|
+
? Object.values(_removedConrols).reduce(function (acc, _a) {
|
|
955
1003
|
var controlRef = _a.controlRef;
|
|
956
1004
|
return mergeRemoveControl(acc, form, controlRef);
|
|
957
1005
|
}, state)
|
|
958
1006
|
: state;
|
|
959
|
-
var updatedBranch = Object.values(
|
|
1007
|
+
var updatedBranch = Object.values(_changedControls)
|
|
960
1008
|
.reverse()
|
|
961
1009
|
.reduce(function (acc, control) {
|
|
962
1010
|
var _a;
|
|
@@ -1149,6 +1197,8 @@ exports.Validators = index;
|
|
|
1149
1197
|
exports.array = array;
|
|
1150
1198
|
exports.build = build;
|
|
1151
1199
|
exports.control = control;
|
|
1200
|
+
exports.getAncestorControls = getAncestorControls;
|
|
1152
1201
|
exports.getArrayItems = getArrayItems;
|
|
1202
|
+
exports.getDescendantControls = getDescendantControls;
|
|
1153
1203
|
exports.group = group;
|
|
1154
1204
|
exports.load = load;
|
package/package.json
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"author": "David Lai",
|
|
15
15
|
"license": "ISC",
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@reactables/core": "^1.0.0
|
|
17
|
+
"@reactables/core": "^1.0.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": "1.0.0
|
|
26
|
+
"version": "1.0.0"
|
|
27
27
|
}
|