如何在mat-stepper中验证FormGroup的数组是否为空
解决Mat-Stepper中FormArray验证不生效的问题
问题核心
你当前的验证不生效,是因为FormArray skillsOffer 和业务数据 job.skillsOffer 完全脱节:验证规则只作用于FormArray,但你操作的是job.skillsOffer,FormArray始终是空数组,导致验证逻辑完全没触发。同时HTML中的表单结构也存在错误,比如formArrayName放置位置不对,错误地给FormArray绑定了formControlName。
修复步骤
1. 新增FormArray的Getter(方便访问)
在组件类中添加一个getter,快速获取skillsOffer这个FormArray:
export class CreateYourJobComponent implements OnInit { public job = new Job(); // ... 其他表单组定义 // 新增getter get skillsOfferFormArray(): FormArray { return this.secondFormGroup.get('skillsOffer') as FormArray; } constructor(private _formBuilder: FormBuilder, public dialog: MatDialog) { } // ... 其他方法 }
2. 同步FormArray与业务数据
修改addSkillsOffer和removeSkills方法,确保每次操作job.skillsOffer时,同步更新FormArray的内容:
修改addSkillsOffer方法:
addSkillsOffer(data: EditOffer) { this.dialog.open(OfferDialogComponent, { data }) .afterClosed().subscribe((res) => { if (!res) return; // 更新业务数据 this.job.skillsOffer = res.skillsOffer; // 清空并同步FormArray this.skillsOfferFormArray.clear(); res.skillsOffer.forEach(skill => { // 仅用于触发验证,无需绑定具体字段,用空FormGroup即可 this.skillsOfferFormArray.push(this._formBuilder.group({})); }); }); }
修改removeSkills方法:
removeSkills(index: number) { // 删除业务数据中的项 this.job.skillsOffer.splice(index, 1); // 同步删除FormArray中的项 this.skillsOfferFormArray.removeAt(index); }
3. 修复HTML表单结构
移除错误的隐藏input,修正formArrayName的位置,并添加验证错误提示:
<mat-horizontal-stepper [linear]="true" #stepper style="margin-left: 20px; margin-top: 1rem"> <!-- 第一个步骤省略 --> <mat-step [stepControl]="secondFormGroup"> <form [formGroup]="secondFormGroup"> <li class="mat-form-field--inline"> <mat-form-field appearance="fill"> <mat-label> {{ "skills.offer" | translate }} </mat-label> <div class="card__body d-flex column"> <!-- 将formArrayName移到*ngFor的父容器上 --> <div class="d-flex align-items-center card__body__list" formArrayName="skillsOffer"> <div *ngFor="let sp of job.skillsOffer; let i = index" class="d-flex justify-content-between pr-1"> <div class="card__text"> {{ sp.name }} <span class="fa fa-remove" (click)="removeSkills(i)"></span> </div> </div> <button class="btn btn-light ml-1" (click)="addSkillsOffer({createJob: true})"> <i class="fa fa-pencil"></i> </button> </div> </div> <!-- 显示验证错误提示 --> <mat-error *ngIf="skillsOfferFormArray.invalid"> 请至少添加一项技能 </mat-error> </mat-form-field> </li> </form> </mat-step> </mat-horizontal-stepper>
4. 可选:自定义数组非空验证器
如果Validators.required对你的场景不够明确,可以自定义一个验证器,确保数组长度大于0:
// 自定义验证器函数 export function nonEmptyArrayValidator(): ValidatorFn { return (control: AbstractControl): ValidationErrors | null => { const formArray = control as FormArray; return formArray.length === 0 ? { emptyArray: true } : null; }; } // 在定义secondFormGroup时使用 secondFormGroup = this._formBuilder.group({ pcKnowledge:[''], skillsOffer: this._formBuilder.array([], nonEmptyArrayValidator()), driveLicense: [''], language: [''], qualifications: [''], });
然后在HTML中修改错误提示的判断:
<mat-error *ngIf="skillsOfferFormArray.hasError('emptyArray')"> 请至少添加一项技能 </mat-error>
修复逻辑说明
- FormArray的验证状态完全由自身内容决定,必须让它和业务数据同步,才能触发正确的验证逻辑
- 修正
formArrayName的位置,确保表单控件与FormArray正确关联 - 移除错误的
formControlName绑定,因为skillsOffer是FormArray而非单个FormControl
内容的提问来源于stack exchange,提问作者TheCoderGuy
相关产品推荐
相关产品推荐

