如何在Angular动态FormArray中超出maxLength时显示错误提示
正确的错误提示写法
你可以通过以下几种方式正确获取动态表单控件的错误状态:
方式1:利用当前FormGroup上下文(推荐)
在[formGroupName]="i"的容器中,直接通过formGroup获取目标控件,结合触摸状态判断是否显示错误:
<div class="col-lg-6" [formGroupName]="i"> <!-- ... 其他表单控件 ... --> <mat-form-field class="col-lg-12" appearance="outline" [floatLabel]="'always'" [hideRequiredMarker]="false"> <mat-label>Script file content</mat-label> <textarea matInput placeholder="Script file content" formControlName="script_file_content" style="height:200px" required></textarea> <!-- 错误提示 --> <mat-error *ngIf="formGroup.get('script_file_content').hasError('maxLength') && formGroup.get('script_file_content').touched"> Max 7 characters </mat-error> </mat-form-field> </div>
如果觉得重复写formGroup.get麻烦,可以给当前FormGroup加模板变量:
<div class="col-lg-6" [formGroupName]="i" #runnerNodeForm="formGroup"> <!-- ... 其他表单控件 ... --> <mat-form-field class="col-lg-12" appearance="outline" [floatLabel]="'always'" [hideRequiredMarker]="false"> <mat-label>Script file content</mat-label> <textarea matInput placeholder="Script file content" formControlName="script_file_content" style="height:200px" required></textarea> <mat-error *ngIf="runnerNodeForm.get('script_file_content').hasError('maxLength') && runnerNodeForm.get('script_file_content').touched"> Max 7 characters </mat-error> </mat-form-field> </div>
方式2:组件中添加辅助方法
在component.ts中添加一个获取指定索引控件的方法:
getScriptContentControl(index: number): FormControl { const runnerNodes = this.workflowAddForm.get('runnerNodes') as FormArray; return runnerNodes.at(index).get('script_file_content') as FormControl; }
然后在模板中调用:
<mat-error *ngIf="getScriptContentControl(i).hasError('maxLength') && getScriptContentControl(i).touched"> Max 7 characters </mat-error>
你之前写法的错误原因
第一种写法:
workflowAddForm.controls.runnerNodes['controls'][i].hasError('maxLength', 'script_file_content')
这里workflowAddForm.controls.runnerNodes是FormArray,但在模板中未正确断言类型,导致访问controls时可能出现类型问题;另外直接通过FormGroup调用hasError时,参数写法不够稳妥,更推荐直接获取目标控件后判断。第二种写法:
workflowAddForm.get('runnerNodes')['controls'][i].value['script_file_content'].hasError('maxLength').value获取的是控件的字符串值,不是FormControl实例,自然没有hasError方法,这是核心错误。第三种写法:
script_file_content.errors?.['maxLength']
模板中无法直接通过formControlName的名称访问FormControl实例,必须通过FormGroup/FormArray来获取,所以模板解析器找不到script_file_content变量,导致报错。
修改后的完整模板片段
<ng-container formArrayName="runnerNodes" *ngFor="let nodes of workflowAddForm.get('runnerNodes')['controls']; let i = index;"> <div class="col-lg-6" [formGroupName]="i" #runnerNodeForm="formGroup"> <div class="form-field-cont runnerFields"> <mat-form-field class="col-lg-12" appearance="outline" [floatLabel]="'always'" [hideRequiredMarker]="false"> <mat-label>Script Name</mat-label> <input matInput placeholder="sample.py" formControlName="script_name" required> </mat-form-field> </div> <div class="form-field-cont"> <mat-form-field class="col-lg-12" appearance="outline" [floatLabel]="'always'" [hideRequiredMarker]="false"> <mat-label>Script file content</mat-label> <textarea matInput placeholder="Script file content" formControlName="script_file_content" style="height:200px" required></textarea> <!-- 长度超限错误提示 --> <mat-error *ngIf="runnerNodeForm.get('script_file_content').hasError('maxLength') && runnerNodeForm.get('script_file_content').touched"> Max 7 characters </mat-error> <!-- 必填项错误提示 --> <mat-error *ngIf="runnerNodeForm.get('script_file_content').hasError('required') && runnerNodeForm.get('script_file_content').touched"> Script content is required </mat-error> </mat-form-field> </div> <div class="deleteIcon" *ngIf="i != 0"> <i class="material-icons cursor-pointer" matTooltip="Remove" (click)="removeRunner(i)" style="color:red;">delete</i> </div> </div> </ng-container>
内容的提问来源于stack exchange,提问作者rk01

