File
controlPathSegments
|
Type
|
string[]
|
import {
AbstractControl,
UntypedFormArray,
UntypedFormControl,
UntypedFormGroup
} from '@angular/forms';
export interface ControlItem {
controlPath: string;
controlPathSegments: string[];
isFormGroup: boolean;
isFormArray: boolean;
control: AbstractControl;
}
/**
* Check if it's a form group and use a TS type guard to let TS know
* that it is indeed a FormGroup in the control flow
*/
export function checkIsFormGroup(control: AbstractControl): control is UntypedFormGroup {
// duck test if this is a FormGroup
return (
control &&
Object.prototype.hasOwnProperty.call(control, 'controls') &&
control instanceof UntypedFormGroup
);
}
export function checkIsFormArray(control: AbstractControl): control is UntypedFormArray {
// duck test if this is a FormGroup
return (
control &&
Object.prototype.hasOwnProperty.call(control, 'controls') &&
control instanceof UntypedFormArray
);
}
export function checkIsFormControl(control: AbstractControl): control is UntypedFormControl {
return control && control instanceof UntypedFormControl;
}
function createControlItem({
control,
controlPathSegments,
isFormGroup,
isFormArray
}: {
controlPathSegments: string[];
isFormGroup: boolean;
isFormArray: boolean;
control: AbstractControl;
}): ControlItem {
return {
controlPath: controlPathSegments.join('.'),
control,
controlPathSegments,
isFormGroup,
isFormArray
};
}
/**
* walkFormGroup
* @param {FormControl|FormGroup|FormArray} controlOrGroup
* @param {object} options allows to set `includeFormGroups` parameter
* @param {string} parentPath
*/
export function walkFormGroup(
controlOrGroup: AbstractControl,
{ includeFormGroups = false } = {},
parentPath: string[] = []
): ControlItem[] {
const items: ControlItem[] = [];
const formGroupItem: ControlItem = createControlItem({
controlPathSegments: parentPath,
isFormGroup: checkIsFormGroup(controlOrGroup),
isFormArray: checkIsFormArray(controlOrGroup),
control: controlOrGroup
});
if (checkIsFormControl(controlOrGroup)) {
items.push(formGroupItem);
} else if (checkIsFormArray(controlOrGroup) || checkIsFormGroup(controlOrGroup)) {
const entries = Object.entries(controlOrGroup.controls);
const isRootFormGroup = parentPath.length === 0;
if (true === includeFormGroups && false === isRootFormGroup) {
items.push(formGroupItem);
}
for (const [path, nestedControl] of entries) {
const currentPath = [...parentPath, path];
items.push(...walkFormGroup(nestedControl, { includeFormGroups }, currentPath));
}
}
return items;
}