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

Angular自定义校验器报Cannot read properties of null (reading 'cannotContainSpace')

问题原因

Angular的表单控件校验通过时,errors 属性的值为 null 而非空对象。你在模板中直接访问 username.errors.cannotContainSpace,当控件没有校验错误时,errors 是 null,读取 null 的属性自然会抛出你遇到的类型错误。

解决方案

方案1:使用可选链操作符(推荐,Angular 12+ 支持)

直接修改模板中所有访问 errors 子属性的代码,加可选链 ? 做空值保护:

<div
  *ngIf="username.errors?.cannotContainSpace && username.touched"
  class="alert alert-danger"
>
  Username cannot contain space.
</div>
<div
  *ngIf="username.errors?.required && username.touched"
  class="alert alert-danger"
>
  Username is required.
</div>
<div
  *ngIf="username.errors?.shouldBeUnique && username.touched"
  class="alert alert-danger"
>
  Username is already taken.
</div>

方案2:使用表单控件自带的 hasError 方法(兼容性最好)

这种写法不需要手动处理空值,框架内部已经做了判断:

<div
  *ngIf="username.hasError('cannotContainSpace') && username.touched"
  class="alert alert-danger"
>
  Username cannot contain space.
</div>
<div
  *ngIf="username.hasError('required') && username.touched"
  class="alert alert-danger"
>
  Username is required.
</div>
<div
  *ngIf="username.hasError('shouldBeUnique') && username.touched"
  class="alert alert-danger"
>
  Username is already taken.
</div>

方案3:先判断 errors 是否存在

在访问子属性前先判断 errors 不为空:

<div
  *ngIf="username.errors && username.errors.cannotContainSpace && username.touched"
  class="alert alert-danger"
>
额外优化建议

你写的自定义校验器中没有处理 control.value 为空的情况,如果控件值为 null 时调用 indexOf 也会抛出类似错误,可以修改校验器代码增加空值判断:

static cannotContainSpace(control: AbstractControl): ValidationErrors | null {
  // 空值直接返回校验通过
  if (!control.value) return null;
  if ((control.value as string).indexOf(' ') >= 0) {
    return { cannotContainSpace: true };
  }
  return null;
}

内容的提问来源于stack exchange,提问作者lionel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 07:57:05