/
utils.ts
121 lines (109 loc) · 3.5 KB
/
utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import { AbstractControl, FormGroup} from '@angular/forms';
function getControlPath(
rootForm: FormGroup,
controlName: string,
control: AbstractControl
): string {
for (const key in rootForm.controls) {
if (rootForm.controls.hasOwnProperty(key)) {
const ctrl = rootForm.get(key);
if (ctrl instanceof FormGroup) {
const path = getControlPath(ctrl, controlName, control);
if (path) {
return key + '.' + path;
}
} else if (ctrl === control) {
return key;
}
}
}
return '';
}
function getGroupPath(
formGroup: FormGroup,
controlName: string,
control: AbstractControl
): string {
for (const key in formGroup.controls) {
if (formGroup.controls.hasOwnProperty(key)) {
const ctrl = formGroup.get(key);
if (ctrl === control) {
return key;
}
if (ctrl instanceof FormGroup) {
const path = getGroupPath(ctrl, controlName, control);
if (path) {
return key + '.' + path;
}
}
}
}
return '';
}
/**
* Calculates the name of an abstract control in a form group
* @param formGroup
* @param control
*/
function findControlNameInGroup(
formGroup:
| { [key: string]: AbstractControl<any, any> }
| AbstractControl<any, any>[],
control: AbstractControl
): string {
return (
Object.keys(formGroup).find(
(name: string) => control === control.parent?.get(name)
) || ''
);
}
/**
* Calculates the field name of a form control: Eg: addresses.shippingAddress.street
* @param rootForm
* @param control
*/
export function getFormControlField(rootForm: FormGroup, control: AbstractControl): string {
const parentFormGroup = control.parent?.controls;
if (!parentFormGroup) {
throw new Error('An ngModel should always be wrapped in a parent FormGroup');
}
const abstractControlName = findControlNameInGroup(parentFormGroup, control);
return getControlPath(rootForm, abstractControlName, control);
}
/**
* Calcuates the field name of a form group Eg: addresses.shippingAddress
* @param rootForm
* @param control
*/
export function getFormGroupField(rootForm: FormGroup, control: AbstractControl): string {
const parentFormGroup = control.parent?.controls;
if (!parentFormGroup) {
throw new Error('An ngModelGroup should always be wrapped in a parent FormGroup');
}
const abstractControlName = findControlNameInGroup(parentFormGroup, control);
return getGroupPath(rootForm, abstractControlName, control);
}
export function mergeValuesAndRawValues<T>(form: FormGroup): T {
// Retrieve the standard values (respecting references)
const value = { ...form.value };
// Retrieve the raw values (including disabled values)
const rawValue = form.getRawValue();
// Recursive function to merge rawValue into value
function mergeRecursive(target: any, source: any) {
Object.keys(source).forEach(key => {
if (target[key] === undefined) {
// If the key is not in the target, add it directly (for disabled fields)
target[key] = source[key];
} else if (typeof source[key] === 'object' && source[key] !== null && !Array.isArray(source[key])) {
// If the value is an object, merge it recursively
mergeRecursive(target[key], source[key]);
}
// If the target already has the key with a primitive value, it's left as is to maintain references
});
}
// Start the merging process only if the form is a FormGroup
if (form instanceof FormGroup) {
mergeRecursive(value, rawValue);
}
return value;
}