@reactables/forms 0.5.2-alpha.0 → 0.5.4-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 +111 -6
- package/dist/Reducers/Hub2/mergePushControl.d.ts +22 -0
- package/dist/RxForm/RxForm.d.ts +4 -6
- package/dist/RxForm/index.d.ts +1 -1
- package/dist/index.js +22 -13
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -2,14 +2,119 @@
|
|
|
2
2
|
|
|
3
3
|
## Description
|
|
4
4
|
|
|
5
|
-
State
|
|
5
|
+
State Management of 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)
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
1. [API](#api)
|
|
16
|
+
1. [RxActions](#api-actions)
|
|
17
|
+
1. [build](#api-build)
|
|
18
|
+
1. [control](#api-control)
|
|
19
|
+
1. [group](#api-group)
|
|
20
|
+
1. [array](#api-array)
|
|
21
|
+
1. [Other Interfaces](#interfaces)
|
|
22
|
+
1. [EffectsAndSources](#effects-sources)
|
|
12
23
|
|
|
13
|
-
The second set is responsible for reacting to the form change in the first store and asynchronous validation.
|
|
14
24
|
|
|
15
|
-
|
|
25
|
+
## Installation <a name="installation"></a>
|
|
26
|
+
|
|
27
|
+
Installation will require [RxJS](https://rxjs.dev/) if not already installed.
|
|
28
|
+
|
|
29
|
+
`npm i rxjs @reactables/forms`
|
|
30
|
+
|
|
31
|
+
## Examples <a name="examples"></a>
|
|
32
|
+
|
|
33
|
+
WIP
|
|
34
|
+
|
|
35
|
+
## API <a name="api"></a>
|
|
36
|
+
|
|
37
|
+
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.
|
|
38
|
+
|
|
39
|
+
### `RxActions` <a name="api-actions"></a>
|
|
40
|
+
|
|
41
|
+
Actions available to trigger state changes on Reactable.
|
|
42
|
+
|
|
43
|
+
```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
|
+
};
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### `build` <a name="api-build"></a>
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
type build = (config: AbstractControlConfig, options?: EffectsAndSources) => Reactable<Form<unknown>, RxFormActions>
|
|
60
|
+
```
|
|
61
|
+
|
|
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).
|
|
63
|
+
|
|
64
|
+
Options can also be provided to declare [Effects and Sources](#effects-sources) for the form Reactable.
|
|
65
|
+
|
|
66
|
+
### `control` <a name="api-control"></a>
|
|
67
|
+
|
|
68
|
+
Function to create a `FormControlConfig` configuration object. Accepts a configuration object or a tuple.
|
|
69
|
+
```typescript
|
|
70
|
+
type control = <T>(config: FormControlConfig<T> | FbControl<T>) => FormControlConfig<T>
|
|
71
|
+
|
|
72
|
+
interface FormControlConfig<T> {
|
|
73
|
+
initialValue: T;
|
|
74
|
+
validators?: ValidatorFn[];
|
|
75
|
+
asyncValidators?: ValidatorAsyncFn[];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
type FbControl<T> = [T, (ValidatorFn | ValidatorFn[])?, (ValidatorAsyncFn | ValidatorAsyncFn[])?];
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### `group` <a name="api-group"></a>
|
|
82
|
+
|
|
83
|
+
Function to create a `FormGroupConfig` configuration object. Accepts a configuration object containing a `controls` dictionary of additional configuration objects generated by [`control`](#api-control), [`group`](#api-group), or [`array`](#api-array).
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
type group = (config: FormGroupConfig) => FormGroupConfig
|
|
87
|
+
|
|
88
|
+
interface FormGroupConfig{
|
|
89
|
+
validators?: ValidatorFn[];
|
|
90
|
+
asyncValidators?: ValidatorAsyncFn[];
|
|
91
|
+
controls: { [key: string]: AbstractControlConfig };
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
### `array` <a name="api-array"></a>
|
|
95
|
+
|
|
96
|
+
Function to create a `FormArrayConfig` configuration object. Accepts a configuration object containing a `controls` array of additional configuration objects generated by [`control`](#api-control), [`group`](#api-group), or [`array`](#api-array).
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
type array = (config: FormArrayConfig) => FormArrayConfig
|
|
100
|
+
|
|
101
|
+
interface FormArrayConfig {
|
|
102
|
+
validators?: ValidatorFn[];
|
|
103
|
+
asyncValidators?: ValidatorAsyncFn[];
|
|
104
|
+
controls: AbstractControlConfig[];
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Other Interfaces <a name="interfaces"></a>
|
|
109
|
+
|
|
110
|
+
#### EffectsAndSources <a name="effects-sources"></a>
|
|
111
|
+
```typescript
|
|
112
|
+
interface EffectsAndSources {
|
|
113
|
+
effects?: Effect<unknown, unknown>[];
|
|
114
|
+
sources?: Observable<Action<unknown>>[] | { [key: string]: Observable<unknown> };
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
| Property | Description |
|
|
118
|
+
| -------- | ----------- |
|
|
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 |
|
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
import { Form, BaseForm } from '../../Models/Controls';
|
|
2
2
|
import { ControlRef } from '../../Models/ControlRef';
|
|
3
|
+
import { FormErrors } from '../../Models/FormErrors';
|
|
3
4
|
export declare const mergePushControl: <T>(state: Form<T>, form: BaseForm<T>, controlRef: ControlRef) => {
|
|
5
|
+
[x: string]: import("../../Models/Controls").FormControl<unknown> | {
|
|
6
|
+
errors: {
|
|
7
|
+
[x: string]: boolean;
|
|
8
|
+
};
|
|
9
|
+
valid: boolean;
|
|
10
|
+
childrenValid: boolean;
|
|
11
|
+
pristineValue: unknown;
|
|
12
|
+
controlRef: ControlRef;
|
|
13
|
+
value: unknown;
|
|
14
|
+
dirty: boolean;
|
|
15
|
+
touched: boolean;
|
|
16
|
+
validatorErrors: FormErrors;
|
|
17
|
+
config: import("../..").AbstractControlConfig;
|
|
18
|
+
key: string;
|
|
19
|
+
asyncValidatorErrors: FormErrors;
|
|
20
|
+
asyncValidateInProgress: {
|
|
21
|
+
[key: string]: boolean;
|
|
22
|
+
[key: number]: boolean;
|
|
23
|
+
};
|
|
24
|
+
pending?: boolean;
|
|
25
|
+
};
|
|
4
26
|
root?: import("../../Models/Controls").FormControl<unknown>;
|
|
5
27
|
};
|
package/dist/RxForm/RxForm.d.ts
CHANGED
|
@@ -5,6 +5,9 @@ import { FormControlConfig, FormArrayConfig, FormGroupConfig, AbstractControlCon
|
|
|
5
5
|
import { ValidatorFn, ValidatorAsyncFn } from '../Models/Validators';
|
|
6
6
|
import { Form } from '../Models/Controls';
|
|
7
7
|
type FbControl<T> = [T, (ValidatorFn | ValidatorFn[])?, (ValidatorAsyncFn | ValidatorAsyncFn[])?];
|
|
8
|
+
export declare const control: <T>(config: FormControlConfig<T> | FbControl<T>) => FormControlConfig<T>;
|
|
9
|
+
export declare const array: (config: FormArrayConfig) => FormArrayConfig;
|
|
10
|
+
export declare const group: (config: FormGroupConfig) => FormGroupConfig;
|
|
8
11
|
export type RxFormActions = {
|
|
9
12
|
updateValues: <T>(payload: ControlChange<T>) => void;
|
|
10
13
|
addControl: (payload: AddControl) => void;
|
|
@@ -15,10 +18,5 @@ export type RxFormActions = {
|
|
|
15
18
|
markControlAsUntouched: (payload: ControlRef) => void;
|
|
16
19
|
resetControl: (payload: ControlRef) => void;
|
|
17
20
|
};
|
|
18
|
-
export declare const
|
|
19
|
-
group: (config: FormGroupConfig) => FormGroupConfig;
|
|
20
|
-
array: (config: FormArrayConfig) => FormArrayConfig;
|
|
21
|
-
control: <T>(config: FormControlConfig<T> | FbControl<T>) => FormControlConfig<T>;
|
|
22
|
-
build: (config: AbstractControlConfig, options?: EffectsAndSources) => Reactable<Form<unknown>, RxFormActions>;
|
|
23
|
-
};
|
|
21
|
+
export declare const build: (config: AbstractControlConfig, options?: EffectsAndSources) => Reactable<Form<unknown>, RxFormActions>;
|
|
24
22
|
export {};
|
package/dist/RxForm/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { build, group, array, control, RxFormActions } from './RxForm';
|
package/dist/index.js
CHANGED
|
@@ -875,12 +875,9 @@ var mergePushControl = function (state, form, controlRef) {
|
|
|
875
875
|
var ancestors = getAncestorControls(controlRef, state)
|
|
876
876
|
.reverse()
|
|
877
877
|
.reduce(function (acc, control, index, arr) {
|
|
878
|
-
var _a
|
|
878
|
+
var _a;
|
|
879
879
|
var formKey = getFormKey(control.controlRef);
|
|
880
880
|
var errors = __assign(__assign({}, form[formKey].validatorErrors), control.asyncValidatorErrors);
|
|
881
|
-
if (!control.childrenValid)
|
|
882
|
-
// If the ancestor control's children were not valid, pushing an item won't change its valid status
|
|
883
|
-
return __assign(__assign({}, acc), (_a = {}, _a[formKey] = __assign(__assign(__assign({}, control), form[formKey]), { errors: errors }), _a));
|
|
884
881
|
var selfValid = !hasErrors(errors);
|
|
885
882
|
var childrenValid = true;
|
|
886
883
|
if (index === 0) {
|
|
@@ -889,9 +886,24 @@ var mergePushControl = function (state, form, controlRef) {
|
|
|
889
886
|
mergedDescendants[getFormKey(controlRef.concat(newItemIndex))].valid;
|
|
890
887
|
}
|
|
891
888
|
else {
|
|
892
|
-
|
|
889
|
+
if (Array.isArray(control.config.controls)) {
|
|
890
|
+
// If control is a FormArray
|
|
891
|
+
childrenValid = control.value.every(function (item, index) {
|
|
892
|
+
var formKey = getFormKey(control.controlRef.concat(index));
|
|
893
|
+
var valid = acc[formKey] === undefined ? state[formKey].valid : acc[formKey].valid;
|
|
894
|
+
return valid;
|
|
895
|
+
});
|
|
896
|
+
}
|
|
897
|
+
else if (control.config.controls) {
|
|
898
|
+
// If control is a FormGroup
|
|
899
|
+
childrenValid = Object.keys(control.value).every(function (childKey) {
|
|
900
|
+
var formKey = getFormKey(control.controlRef.concat(childKey));
|
|
901
|
+
var valid = acc[formKey] === undefined ? state[formKey].valid : acc[formKey].valid;
|
|
902
|
+
return valid;
|
|
903
|
+
});
|
|
904
|
+
}
|
|
893
905
|
}
|
|
894
|
-
return __assign(__assign({}, acc), (
|
|
906
|
+
return __assign(__assign({}, acc), (_a = {}, _a[formKey] = __assign(__assign(__assign({}, control), form[formKey]), { errors: errors, valid: selfValid && childrenValid, childrenValid: childrenValid }), _a));
|
|
895
907
|
}, {});
|
|
896
908
|
var controlBranchUpdated = __assign(__assign({}, ancestors), mergedDescendants);
|
|
897
909
|
return __assign(__assign({}, state), controlBranchUpdated);
|
|
@@ -980,12 +992,6 @@ var build = function (config, options) {
|
|
|
980
992
|
state$: rxHub2.state$.pipe(operators.filter(function (form) { return form !== null; })),
|
|
981
993
|
actions: rxHub1.actions
|
|
982
994
|
};
|
|
983
|
-
};
|
|
984
|
-
var RxForm = {
|
|
985
|
-
group: group,
|
|
986
|
-
array: array,
|
|
987
|
-
control: control,
|
|
988
|
-
build: build
|
|
989
995
|
};
|
|
990
996
|
|
|
991
997
|
var getArrayItems = function (controlRef, form) {
|
|
@@ -998,6 +1004,9 @@ var getArrayItems = function (controlRef, form) {
|
|
|
998
1004
|
};
|
|
999
1005
|
|
|
1000
1006
|
exports.ControlModels = Controls;
|
|
1001
|
-
exports.RxForm = RxForm;
|
|
1002
1007
|
exports.Validators = index;
|
|
1008
|
+
exports.array = array;
|
|
1009
|
+
exports.build = build;
|
|
1010
|
+
exports.control = control;
|
|
1003
1011
|
exports.getArrayItems = getArrayItems;
|
|
1012
|
+
exports.group = group;
|
package/package.json
CHANGED
|
@@ -14,12 +14,14 @@
|
|
|
14
14
|
"author": "David Lai",
|
|
15
15
|
"license": "ISC",
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@reactables/core": "^0.5.
|
|
18
|
-
"lodash.clonedeep": "^4.5.0",
|
|
17
|
+
"@reactables/core": "^0.5.4-alpha.0",
|
|
19
18
|
"lodash.isequal": "^4.5.0"
|
|
20
19
|
},
|
|
21
20
|
"peerDependencies": {
|
|
22
21
|
"rxjs": "^6.0.0 || ^7.0.0"
|
|
23
22
|
},
|
|
24
|
-
"
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"lodash.clonedeep": "^4.5.0"
|
|
25
|
+
},
|
|
26
|
+
"version": "0.5.4-alpha.0"
|
|
25
27
|
}
|