Skip to content

Commit adbe550

Browse files
committed
feat(api): change the api to be more angularish
1 parent b6346e2 commit adbe550

25 files changed

+720
-1180
lines changed

README.md

Lines changed: 27 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -87,56 +87,56 @@ With this setup, you’ll have an extensive API to query the store and update th
8787

8888
## API
8989

90-
- `selectValid()` - Whether the control is valid
90+
- `valueChanges()` - Observe the control's value
9191

9292
```ts
93-
const isFormValid$ = formsManager.selectValid('onboarding');
94-
const isNameValid$ = formsManager.selectValid('onboarding', 'name');
93+
const value$ = formsManager.valueChanges('onboarding');
94+
const nameValue$ = formsManager.valueChanges<string>('onboarding', 'name');
9595
```
9696

97-
- `selectDirty()` - Whether the control is dirty
97+
- `validityChanges()` - Whether the control is valid
9898

9999
```ts
100-
const isFormDirty$ = formsManager.selectDirty('onboarding');
101-
const isNameDirty$ = formsManager.selectDirty('onboarding', 'name');
100+
const valid$ = formsManager.validityChanges('onboarding');
101+
const nameValid$ = formsManager.validityChanges('onboarding', 'name');
102102
```
103103

104-
- `selectDisabled()` - Whether the control is disabled
104+
- `dirtyChanges()` - Whether the control is dirty
105105

106106
```ts
107-
const isFormDisabled$ = formsManager.selectDisabled('onboarding');
108-
const isNameDisabled$ = formsManager.selectDisabled('onboarding', 'name');
107+
const dirty$ = formsManager.dirtyChanges('onboarding');
108+
const nameDirty$ = formsManager.dirtyChanges('onboarding', 'name');
109109
```
110110

111-
- `selectValue()` - Observe the control's value
111+
- `disableChanges()` - Whether the control is disabled
112112

113113
```ts
114-
const value$ = formsManager.selectValue('onboarding');
115-
const nameValue$ = formsManager.selectValue<string>('onboarding', 'name');
114+
const disabled$ = formsManager.disableChanges('onboarding');
115+
const nameDisabled$ = formsManager.disableChanges('onboarding', 'name');
116116
```
117117

118-
- `selectErrors()` - Observe the control's errors
118+
- `errorsChanges()` - Observe the control's errors
119119

120120
```ts
121-
const errors$ = formsManager.selectErrors('onboarding');
122-
const nameErros$ = formsManager.selectErrors('onboarding', 'name');
121+
const errors$ = formsManager.errorsChanges<Errors>('onboarding');
122+
const nameErros$ = formsManager.errorsChanges<Errors>('onboarding', 'name');
123123
```
124124

125-
- `selectControl()` - Observe the control's state
125+
- `controlChanges()` - Observe the control's state
126126

127127
```ts
128-
const control$ = formsManager.selectControl('onboarding');
129-
const nameControl$ = formsManager.selectControl('onboarding', 'name');
128+
const control$ = formsManager.controlChanges('onboarding');
129+
const nameControl$ = formsManager.controlChanges<string>('onboarding', 'name');
130130
```
131131

132132
- `getControl()` - Get the control's state
133133

134134
```ts
135135
const control = formsManager.getControl('onboarding');
136-
const nameControl = formsManager.getControl('onboarding', 'name');
136+
const nameControl = formsManager.getControl<string>('onboarding', 'name');
137137
```
138138

139-
`selectControl` and `getControl` will return the following state:
139+
`controlChanges` and `getControl` will return the following state:
140140

141141
```ts
142142
{
@@ -153,18 +153,6 @@ const nameControl = formsManager.getControl('onboarding', 'name');
153153
}
154154
```
155155

156-
- `selectForm()` - Observe the form's state
157-
158-
```ts
159-
const form$ = formsManager.selectForm('onboarding');
160-
```
161-
162-
- `getForm()` - Get the form's state
163-
164-
```ts
165-
const form = formsManager.getForm('onboarding');
166-
```
167-
168156
- `hasForm()` - Whether the form exists
169157

170158
```ts
@@ -204,6 +192,12 @@ formsManager.destroy('onboarding');
204192
formsManager.destroy();
205193
```
206194

195+
- `controlDestroyed()` - Emits when the control is destroyed
196+
197+
```ts
198+
formsManager.controlChanges('login').pipe(takeUntil(controlDestroyed('login')));
199+
```
200+
207201
## Persist to Local Storage
208202

209203
In the `upsert` method, pass the `persistState` flag:
@@ -304,7 +298,7 @@ export class OnboardingComponent {
304298
constructor(private formsManager: NgFormsManager<AppForms>, private builder: FormBuilder) {}
305299

306300
ngOnInit() {
307-
this.formsManager.selectValue('onboarding').subscribe(value => {
301+
this.formsManager.valueChanges('onboarding').subscribe(value => {
308302
// value now typed as AppForms['onboarding']
309303
});
310304
}

package-lock.json

Lines changed: 30 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
"@angular/router": "~7.0.0",
2626
"@schuchard/prettier": "^3.1.0",
2727
"core-js": "^2.5.4",
28-
"lodash.isequal": "^4.5.0",
2928
"ngx-semantic-version": "^1.2.1",
29+
"ngx-take-until-destroy": "^5.4.0",
3030
"rxjs": "~6.3.3",
3131
"zone.js": "~0.8.26"
3232
},

projects/ngneat/forms-manager/ng-package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
"lib": {
55
"entryFile": "src/public_api.ts"
66
},
7-
"whitelistedNonPeerDependencies": ["lodash.isequal"]
7+
"whitelistedNonPeerDependencies": ["fast-deep-equal"]
88
}

projects/ngneat/forms-manager/package.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,5 @@
2121
"name": "Netanel Basal",
2222
"email": "[email protected]",
2323
"url": "https://netbasal.com"
24-
},
25-
"dependencies": {
26-
"lodash.isequal": "^4.5.0"
2724
}
2825
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms';
2+
import { Control, ControlFactory, HashMap } from './types';
3+
import { clone } from './utils';
4+
5+
export function toStore<FormsState>(name: keyof FormsState, control: AbstractControl) {
6+
let value;
7+
8+
if (control instanceof FormControl) {
9+
value = buildValue(control);
10+
return value;
11+
}
12+
13+
if (control instanceof FormGroup || control instanceof FormArray) {
14+
value = buildValue(control);
15+
16+
for (const key of Object.keys(control.controls)) {
17+
const current = control.controls[key];
18+
if (current instanceof FormGroup || current instanceof FormArray) {
19+
value.controls[key] = toStore(name, current);
20+
} else {
21+
value.controls[key] = buildValue(current);
22+
}
23+
}
24+
}
25+
26+
return value;
27+
}
28+
29+
export function handleFormArray(
30+
formValue: HashMap | any[],
31+
control: AbstractControl,
32+
arrControlFactory: ControlFactory | HashMap<ControlFactory>
33+
) {
34+
if (control instanceof FormArray) {
35+
clearFormArray(control as FormArray);
36+
if (!arrControlFactory) {
37+
throw new Error('Please provide arrControlFactory');
38+
}
39+
formValue.forEach((v, i) =>
40+
(control as FormArray).insert(i, (arrControlFactory as Function)(v))
41+
);
42+
} else {
43+
Object.keys(formValue).forEach(controlName => {
44+
const value = formValue[controlName];
45+
if (Array.isArray(value) && control.get(controlName) instanceof FormArray) {
46+
if (!arrControlFactory || (arrControlFactory && !(controlName in arrControlFactory))) {
47+
throw new Error(`Please provide arrControlFactory for ${controlName}`);
48+
}
49+
const current = control.get(controlName) as FormArray;
50+
const fc = arrControlFactory[controlName];
51+
clearFormArray(current);
52+
value.forEach((v, i) => current.insert(i, fc(v)));
53+
}
54+
});
55+
}
56+
}
57+
58+
export function deleteControl(snapshot, controls: any[]) {
59+
return Object.keys(snapshot).reduce((acc, currentFormName) => {
60+
if (controls.includes(currentFormName) === false) {
61+
acc[currentFormName] = snapshot[currentFormName];
62+
}
63+
return acc;
64+
}, {});
65+
}
66+
67+
export function findControl(control: Control, path: string) {
68+
const [first, ...rest] = path.split('.');
69+
if (rest.length === 0) {
70+
return control.controls[first];
71+
}
72+
73+
return rest.reduce((current: Control, name: string) => {
74+
return current.controls.hasOwnProperty(name) ? current.controls[name] : null;
75+
}, control.controls[first]);
76+
}
77+
78+
export function buildValue(control: Partial<AbstractControl>): Control {
79+
const value = {
80+
value: clone(control.value), // Clone object to prevent issue with third party that would be affected by store freezing.
81+
rawValue: (control as any).getRawValue ? (control as any).getRawValue() : null,
82+
valid: control.valid,
83+
dirty: control.dirty,
84+
invalid: control.invalid,
85+
disabled: control.disabled,
86+
errors: control.errors,
87+
touched: control.touched,
88+
pristine: control.pristine,
89+
pending: control.pending,
90+
};
91+
92+
if (control instanceof FormGroup || control instanceof FormArray) {
93+
value['controls'] = control instanceof FormArray ? [] : {};
94+
}
95+
96+
return value;
97+
}
98+
99+
export function clearFormArray(control: FormArray) {
100+
while (control.length !== 0) {
101+
control.removeAt(0);
102+
}
103+
}

projects/ngneat/forms-manager/src/lib/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export function mergeConfig(
2020
inlineConfig: Partial<Config>
2121
) {
2222
return {
23+
...defaults,
2324
storage: {
2425
...defaults.storage,
2526
...providerConfig.storage,

0 commit comments

Comments
 (0)