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

Angular自定义单选按钮报NullInjectorError无NgControl提供者如何解决

问题解决方案

你的报错根因是继承了Angular内置的RadioControlValueAccessor类,但没有处理它的NgControl依赖,该类本身设计为配合Angular表单指令使用,默认需要注入NgControl实例,按以下两步修改即可修复:

1. 组件类补充依赖注入配置

修改radio-button.component.ts,给组件添加构造函数,用@Optional()装饰器标记NgControl为可选依赖,避免无表单上下文时抛出注入错误:

// 先导入必要的装饰器和类
import { Optional, Self, NgControl } from '@angular/forms';

@Component({
  selector: 'fls-radio-button',
  templateUrl: './radio-button.component.html',
  styleUrls: ['./radio-button.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => RadioButtonComponent),
      multi: true
    }
  ],
  encapsulation: ViewEncapsulation.None
})
export class RadioButtonComponent extends RadioControlValueAccessor {
  @HostBinding('class') classes = 'fls-radio-button';

  @Input() id: string;
  @Input() name: string;
  @Input() value: SimpleFieldValue;
  @Input() label: string;
  @Input() disabled = false;
  @Input() checked = false;

  // 新增构造函数
  constructor(@Optional() @Self() ngControl: NgControl) {
    super();
    if (ngControl) {
      ngControl.valueAccessor = this;
    }
  }

  setDisabledState(isDisabled: boolean): void {
    this.disabled = isDisabled;
  }
}

如果你不想依赖Angular的表单上下文,也可以选择不继承RadioControlValueAccessor,自行完整实现ControlValueAccessor接口的所有方法,即可彻底消除NgControl依赖。

2. 单元测试调整

你现有测试是直接创建组件实例,没有模拟表单绑定的使用场景,补充构造函数的@Optional()装饰器后测试即可正常运行。如果需要模拟真实的表单使用场景,可以在测试中创建一个包装组件,用formControl或ngModel绑定你的单选按钮组件测试即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 14:54:07