Unable to patch data to FormArray
By your question you want to add new Student
to resultList
.
First of all, you need to know FormArray
is an array of AbstractControl.
You can add to array only type of AbstractControl not other.
To simplify task prefer to use FormBuilder
:
constructor(private fb: FormBuilder) {}
createForm() {
this.myform = this.fb.group({
firstName: ['', [Validators.required, Validators.minLength(4)]],
lastName: [],
gender: ['male'],
dob: [],
qualification: [],
resultList: new FormArray([])
});
}
As you can see before filling resultList FormArray
, it's mapped to FormGroup:
onSave() {
let stud: Student = new Student();
stud.firstName = 'Hello';
stud.lastName = 'World';
stud.qualification = 'SD';
this.studList.push(stud);
let studFg = this.fb.group({
firstName: [stud.firstName, [Validators.required, Validators.minLength(4)]],
lastName: [stud.lastName],
gender: [stud.gender],
dob: [stud.dob],
qualification: [stud.qualification],
})
let formArray = this.myform.controls['resultList'] as FormArray;
formArray.push(studFg);
console.log(formArray.value)
}
FormBuilder - Creates an AbstractControl from a user-specified configuration.
It is essentially syntactic sugar that shortens the new FormGroup(), new FormControl(), and new FormArray() boilerplate that can build up in larger forms.
Also, in html formControlName bound to <p>
element, It's not an input and you can't bind to not form elements like div/p/span...:
<tbody>
<tr *ngFor="let item of myform.controls.resultList.controls; let i = index" [formGroupName]="i">
<td><p formControlName="firstName"></p></td> <==== Wrong element
</tr>
</tbody>
So, I think you just want to show added students in table. Then iterate over studList and show it's value in table:
<tbody>
<tr *ngFor="let item of studList; let i = index" [formGroupName]=i>
<td>
<p> {{item.firstName}} </p>
</td>
</tr>
</tbody>
Patching value
Take care when patching array. Because patchValue of FormArray patches values by the index:
patchValue(value: any[], options: {onlySelf?: boolean, emitEvent?: boolean} = {}): void {
value.forEach((newValue: any, index: number) => {
if (this.at(index)) {
this.at(index).patchValue(newValue, {onlySelf: true, emitEvent: options.emitEvent});
}
});
this.updateValueAndValidity(options);
}
So, code below it patches the element at index=0: First indexed value of this.myform.controls['resultList'] as FormArray
will be replaced with:
let stud1 = new Student();
stud1.firstName = 'FirstName';
stud1.lastName = 'LastName';
stud1.qualification = 'FFF';
formArray.patchValue([stud1]);
Your case doesn't work because patchValue requires some controls in array. In your case there is no controls in array. Look source code.
StackBlitz Demo
First try with this steps and make sure are you on correct way
Because in your scenario you are patching the object to formArray ,so you have to parse that object first & check once have you imported ReactiveFormsModule in your app.module.ts.