I'm trying to build a function that will produce a copy of a given FormGroup
. I started with:
function copyForm(form: FormGroup): FormGroup {
const copy = new FormGroup({});
for (let key of Object.keys(form.value)) {
const control = form.controls[key];
/* Copy the data from the control into a new control */
const copyControl = new FormControl({[key]: control.value});
copy.addControl(key, copyControl);
}
But that doesn't work if there is a FormArray
or FormGroup
. This one might work if it were recursive, but I couldn't get a good handle on it.
I also attempted to solve it with
function copyForm(form: FormGroup): FormGroup {
const copy = new FormGroup({});
for (let key of Object.keys(form.value)) {
const control = form.controls[key];
const copyControl = new FormControl({...control.value});
copy.addControl(key, copyControl);
}
return copy;
}
But that didn't work for double-nested FormGroups
, any FormArrays
or regular FormControls
...
I also tried:
function copyForm(form: FormGroup): FormGroup {
const copy = new FormGroup(Object.assign({}, form.value));
return copy;
}
But that gives me the error:
ERROR TypeError: control.setParent is not a function
I'm stumped.
I personally use lodash cloneDeep() function found here:
https://lodash.com/docs/#cloneDeep
I use it this way:
const newFormGroup: any = _.cloneDeep(myFormGroup);
And you if you want it strongly typed, you can add
as FormGroup
as @Andre Elrico suggested in the comments:const newFormGroup = _.cloneDeep(myFormGroup) as FormGroup;
If you have simple FormGroups that contain only FormControls (i.e. not FormGroups or FormArrays), and you know their structure in advance, then this is a simple solution:
Note: by using
initaliseFormGroup
for initalising the original FormGroup, you will match the validators for each control.If you have more complex forms (with child FormGroups), or want to clone them dynamically without knowing their structure in advance, then the other answers will better suited.
This is the deep copy function I came up with which also retains the associated validator / async validator functions and disabled status of each AbstractControl.
This is how I would do it:
I'm using
getRawValue()
instead ofvalue
, becausevalue
won't include controls which are disabled.