Reputation: 103
I have a dynamic formArray, saving the data and all is working fine but I am having issue patching values, also I couldn't find any exact solutions online.
Below is the code,
<form [formGroup]="educationAndExperienceForm">
<div formArrayName="educationForm">
<div *ngFor="let education of educationAndExperienceForm.controls.educationForm['controls'];let i = index;"
[formGroupName]="i">
<h6 class="text-left circularBold" *ngIf="i == 0"><b>Highest Qualification</b></h6>
<input type="text" class="education-inputs w-100 mt-3" placeholder="School/College/University"
formControlName="school"
[ngClass]="{ 'input-error': submitted && educationAndExperienceForm.controls.educationForm.controls[i].invalid }">
<input type="text" class="education-inputs w-100 mt-3" placeholder="Degree Ex: Master's"
formControlName="degree"
[ngClass]="{ 'input-error': submitted && educationAndExperienceForm.controls.educationForm.controls[i].invalid }">
<input type="text" class="education-inputs w-100 mt-3"
placeholder="Field of Education Ex: Computer Science" formControlName="specialization"
[ngClass]="{ 'input-error': submitted && educationAndExperienceForm.controls.educationForm.controls[i].invalid }">
<div class="text-left">
<input type="text" class="education-inputs w-100 mt-3" placeholder="Graduate Year"
formControlName="passed_year"
[ngClass]="{ 'input-error': submitted && educationAndExperienceForm.controls.educationForm.controls[i].invalid }">
</div>
<div class="row text-right">
<div class="col-10"></div>
<div class="col-1">
<button type="button" class="btn deleteBtn" (click)="removeEducationFormGroup()">
<i class="fa fa-remove" style="font-size: 24px;" aria-hidden="true"></i>
</button>
</div>
</div>
<div class="text-left" *ngIf="!showAddAfterEducationHeading">
<button type="button" class="btn btn-light circularMedium mb-3 transparentBtn"
(click)="addEducationFormGroup()">
Add Education
</button>
</div>
</div>
<div class="text-left" *ngIf="showAddAfterEducationHeading">
<button type="button" class="btn btn-light circularMedium mb-3 transparentBtn"
(click)="addEducationFormGroup()">
Add Education
</button>
</div>
</div>
</form>
TS File
this.educationAndExperienceForm = this.fb.group({
'educationForm': this.fb.array([this.createEducationFormGroup()])
});
private createEducationFormGroup(): FormGroup {
return this.educationForm = this.fb.group({
'school': ['', Validators.required],
'degree': ['', Validators.required],
'specialization': ['', Validators.required],
'passed_year': ['', Validators.required]
})
}
Below is the code I tried for patching values,
1. One way
fetchQualificationById(){
this.apiService.fetchQualificationById(this.expertId).subscribe(res => {
console.log("Response Ed = "+JSON.stringify(res));
this.qualificationData = res['expertsQualification'];
});
let school = this.qualificationData['school'];
let degree = this.qualificationData['degree'];
let specialization = this.qualificationData['specialization'];
let passed_year = this.qualificationData['passed_year'];
this.educationAndExperienceForm.controls.educationForm.patchValue({
'school': school,
'degree': degree,
'specialization': specialization,
'passed_year': passed_year
})
// console.log("Get Qualification = "+JSON.stringify(this.educationAndExperienceForm.controls.educationForm.value))
}
2. Second way
fetchQualificationById(){
this.apiService.fetchQualificationById(this.expertId).subscribe(res => {
console.log("Response Ed = "+JSON.stringify(res));
this.qualificationData = res['expertsQualification'];
for (let education=0; education < res['expertsQualification'].length; education++){
const educationFormArray = this.educationAndExperienceForm.get("educationForm") as FormArray;
}
});
}
For the first way I use I'm getting cannot use forEach.. error
Edited
Here there's only one array but we could one empty array, why is that? Below is my ts code
@Component({
selector: 'app-expert-education',
templateUrl: './expert-education.component.html',
styleUrls: ['./expert-education.component.css']
})
export class ExpertEducationComponent implements OnInit {
educationForm: FormGroup;
educationAndExperienceForm: FormGroup;
experienceForm: FormGroup;
submitted: boolean;
showAddAfterEducationHeading: boolean;
showAddAfterExperienceHeading: boolean;
expertId;
qualificationData: QualificationModel[] = [];
experienceData: ExperienceModel[] = [];
constructor(
private route: Router,
private fb: FormBuilder,
private apiService: ApiService
) {
this.submitted = false;
}
ngOnInit(): void {
// this.educationForm = this.fb.group({
// 'school': ['', Validators.required],
// 'degree': ['', Validators.required],
// 'field': ['', Validators.required],
// 'graduatedYear': ['', Validators.required],
// 'experience': ['', Validators.required],
// 'designation': ['', Validators.required],
// 'company': ['', Validators.required]
// })
this.expertId = sessionStorage.getItem('id_expert');
this.educationAndExperienceForm = this.fb.group({
'educationForm': this.fb.array([this.createEducationFormGroup()]),
'experienceForm': this.fb.array([this.createExperienceFormGroup()])
});
this.showAddAfterEducationHeading = false;
this.showAddAfterExperienceHeading = true;
this.fetchQualificationById();
this.fetchExperienceById();
}
addEducationFormGroup() {
this.showAddAfterEducationHeading = true;
const education = this.educationAndExperienceForm.get('educationForm') as FormArray;
education.push(this.createEducationFormGroup());
}
addExperienceFormGroup() {
this.showAddAfterExperienceHeading = true;
const experience = this.educationAndExperienceForm.get('experienceForm') as FormArray;
experience.push(this.createExperienceFormGroup());
}
removeEducationFormGroup(index) {
const education = this.educationAndExperienceForm.get('educationForm') as FormArray
if (education.length > 1) {
education.removeAt(index);
} else {
education.reset();
}
}
removeExperienceFormGroup(index) {
const experience = this.educationAndExperienceForm.get('experienceForm') as FormArray
if (experience.length > 1) {
experience.removeAt(index);
} else {
experience.reset();
}
}
private createEducationFormGroup(): FormGroup {
return this.educationForm = this.fb.group({
'school': ['', Validators.required],
'degree': ['', Validators.required],
'specialization': ['', Validators.required],
'passed_year': ['', Validators.required]
})
}
private createExperienceFormGroup(): FormGroup {
return this.experienceForm = this.fb.group({
'duration': ['', Validators.required],
'designation': ['', Validators.required],
'company_name': ['', Validators.required]
})
}
onSubmit() {
this.submitted = true;
console.log("Form = " + JSON.stringify(this.educationAndExperienceForm.controls.educationForm.value) + "\nValid = " + this.educationAndExperienceForm.valid)
if (this.educationAndExperienceForm.valid) {
this.apiService.saveExpertEducationAndExperience(this.educationAndExperienceForm.controls.educationForm.value, this.educationAndExperienceForm.controls.experienceForm.value, this.expertId).subscribe(res => {
console.log("Expert education & exp res = " + JSON.stringify(res));
this.route.navigate(['/expert-welcome/expert-services']);
})
}
}
back() {
this.route.navigate(['/expert-welcome/expert-profile']);
}
fetchQualificationById() {
this.apiService.fetchQualificationById(this.expertId).subscribe(res => {
this.qualificationData = res['expertsQualification'];
const control = <FormArray>this.educationAndExperienceForm.controls['educationForm'];
this.qualificationData.forEach(x => {
control.push(this.fb.group({
school: [x.school, Validators.required],
degree: [x.degree, Validators.required],
specialization: [x.specialization, Validators.required],
passed_year: [x.passed_year, Validators.required]
}));
});
});
}
fetchExperienceById() {
this.apiService.fetchExperienceById(this.expertId).subscribe(res => {
this.experienceData = res['expertExperience'];
const control = <FormArray>this.educationAndExperienceForm.controls['experienceForm'];
this.experienceData.forEach(x => {
control.push(this.fb.group({
duration: [x.duration, Validators.required],
designation: [x.designation, Validators.required],
company_name: [x.company_name, Validators.required],
}));
});
});
}
}
Any help is appreciated.
Upvotes: 2
Views: 1625
Reputation: 434
The problem seems that patchValue is not able to fill formarrays. You can fill formarrays like regular arrays with push().
Assuming that your this.qualificationData is an array containing many "expertsQualification"s (type Array) and the class/interface ExpertsQualification has the properties "school", "degree", "specialization" and "passed_year" you could do the following:
(this.educationAndExperienceForm.controls.educationForm as FormArray).reset(); //reset the FormArray
this.qualificationData.forEach(x => {
(this.educationAndExperienceForm.controls.educationForm as FormArray)
.push(this.fb.group({
school: [x.school, Validators.required],
degree: [x.degree, Validators.required],
specialization: [x.specialization, Validators.required],
passed_year: [x.passed_year, Validators.required]
});
};
.. so that you loop through your array and for each element you push a formgroup to the formarray. Please note tht it's very important to cast it to FormArray like
(this.educationAndExperienceForm.controls.educationForm as FormArray)
If you don't do this, it will stay an AbstractControl and you won't be able to use the array functions like push, pull etc.
Upvotes: 5