You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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网格布局升级前正常,怀疑是初始值处理错误导致。

问题根源

  1. 模板绑定错误:formGroupName="i"使用字符串字面量,Angular会尝试查找名为"i"的FormGroup,而非索引i对应的控件,导致找不到控件引发报错。
  2. Input属性未处理变化:@Input()的cfsPeriods和year可能异步传入,但组件未实现ngOnChanges,表单未重新构建,初始值未正确加载。
  3. 手动设置input的value:input标签同时使用value="{{roundedAmount(myPeriods[i])}}"和formControlName="Amount",导致表单控件值与DOM值冲突,引发渲染异常。
  4. 表单未初始化时的空引用:模板直接访问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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 22:25:21