Angular8升级至14后FormArray报错:Cannot read properties of null
Angular 8升级到14后FormArray报错
Cannot read properties of null (reading '_rawValidators')及渲染异常解决 问题重现
将应用从Angular 8升级到14后,FormArray组件出现以下报错:
cfs-detail.component.html:13 ERROR TypeError: Cannot read properties of null (reading '_rawValidators') at getControlValidators (forms.mjs:901:20) at setUpValidators (forms.mjs:3065:24) at setUpFormContainer (forms.mjs:3182:5) at FormGroupDirective._setUpFormContainer (forms.mjs:4996:9) at FormGroupDirective.addFormGroup (forms.mjs:4883:14) at FormGroupName.ngOnInit (forms.mjs:3732:28) at callHook (core.mjs:2498:22) at callHooks (core.mjs:2467:17) at executeInitAndCheckHooks (core.mjs:2418:9) at selectIndexInternal (core.mjs:9826:17)
同时表单数组初始加载显示不符合预期,切换控件后显示逐渐恢复正常,CSS网格布局升级前正常,怀疑是初始值处理错误导致。
问题根源
- 模板绑定错误:
formGroupName="i"使用字符串字面量,Angular会尝试查找名为"i"的FormGroup,而非索引i对应的控件,导致找不到控件引发报错。 - Input属性未处理变化:
@Input()的cfsPeriods和year可能异步传入,但组件未实现ngOnChanges,表单未重新构建,初始值未正确加载。 - 手动设置input的value:input标签同时使用
value="{{roundedAmount(myPeriods[i])}}"和formControlName="Amount",导致表单控件值与DOM值冲突,引发渲染异常。 - 表单未初始化时的空引用:模板直接访问
periods12.controls,当myFormGroup未初始化时返回null,触发后续错误。
解决方案
1. 修复FormGroupName绑定
将字符串字面量改为属性绑定,同时添加空值安全操作符避免空引用:
<ng-container *ngFor="let perFrm of periods12?.controls ;let i = index;" [formGroupName]="i">
2. 移除Input的手动Value绑定
删除手动设置的value属性,依赖formControlName自动同步值:
<input class="fieldvalue cfs {{showBy}} {{ monthShortName(myPeriods[i]) }}" type="text" formControlName="Amount" />
3. 实现ngOnChanges处理Input变化
添加ngOnChanges钩子,在输入属性变化时重新处理表单:
import { Component, OnInit, OnChanges, SimpleChanges, OnDestroy } from '@angular/core'; import { Subscription } from 'rxjs'; export class cfs12MonthsComponent implements OnInit, OnChanges, OnDestroy { // ... 现有代码 private valueChangesSubscription?: Subscription; ngOnChanges(changes: SimpleChanges): void { if (changes['cfsPeriods'] || changes['year']) { if (this.cfsPeriods && this.year) { this.filterMyPeriods(); this.buildForm(); this.populateForm(); } } } buildForm(){ // 清理之前的订阅避免内存泄漏 this.valueChangesSubscription?.unsubscribe(); this.myFormGroup = this.myFormBuilder.group( { periods : this.myFormBuilder.array([]) },{ updateOn: "blur" } ); this.valueChangesSubscription = this.myFormGroup.valueChanges.subscribe((data: any) => { this.saveMainForm(); }); } ngOnDestroy(): void { this.valueChangesSubscription?.unsubscribe(); } }
4. 确保表单初始化后再渲染
在模板中添加myFormGroup空值判断,避免未初始化时渲染控件:
<ng-container *ngIf="myFormGroup; else loading" [formGroup]="myFormGroup"> <ng-container formArrayName="periods"> <ng-container *ngFor="let perFrm of periods12?.controls ;let i = index;" [formGroupName]="i"> <!-- 现有控件代码 --> </ng-container> </ng-container> </ng-container>
内容的提问来源于stack exchange,提问作者greg
相关产品推荐
相关产品推荐

