如何在 Angular 10 中修补动态表单数组的值?
How to patch values for a dynamic form array in Angular 10?
我有一个动态 formArray,正在保存数据并且一切正常,但我在修补值时遇到问题,而且我无法在线找到任何确切的解决方案。
下面是代码,
<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 文件
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]
})
}
下面是我尝试修补值的代码,
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;
}
});
}
对于我使用的第一种方式,我发现无法使用 forEach.. 错误
已编辑
这里只有一个数组,但我们可以用一个空数组,这是为什么呢?下面是我的 ts 代码
@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],
}));
});
});
}
}
感谢任何帮助。
问题似乎是 patchValue 无法填充数组。您可以使用 push() 像常规数组一样填充 formarrays。
假设您的 this.qualificationData 是一个包含许多“expertsQualification”(数组类型)的数组,并且 class/interface ExpertsQualification 具有属性“school”、“degree”、“specialization”和“ passed_year" 您可以执行以下操作:
(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]
});
};
.. 这样你就可以遍历你的数组,并为每个元素将一个表单组推送到表单数组。请注意将它转换为 FormArray 非常重要,例如
(this.educationAndExperienceForm.controls.educationForm as FormArray)
如果不这样做,它将保留为 AbstractControl,您将无法使用推、拉等数组函数
我有一个动态 formArray,正在保存数据并且一切正常,但我在修补值时遇到问题,而且我无法在线找到任何确切的解决方案。
下面是代码,
<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 文件
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]
})
}
下面是我尝试修补值的代码,
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;
}
});
}
对于我使用的第一种方式,我发现无法使用 forEach.. 错误
已编辑
这里只有一个数组,但我们可以用一个空数组,这是为什么呢?下面是我的 ts 代码
@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],
}));
});
});
}
}
感谢任何帮助。
问题似乎是 patchValue 无法填充数组。您可以使用 push() 像常规数组一样填充 formarrays。
假设您的 this.qualificationData 是一个包含许多“expertsQualification”(数组类型)的数组,并且 class/interface ExpertsQualification 具有属性“school”、“degree”、“specialization”和“ passed_year" 您可以执行以下操作:
(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]
});
};
.. 这样你就可以遍历你的数组,并为每个元素将一个表单组推送到表单数组。请注意将它转换为 FormArray 非常重要,例如
(this.educationAndExperienceForm.controls.educationForm as FormArray)
如果不这样做,它将保留为 AbstractControl,您将无法使用推、拉等数组函数