Angular响应式表单注入NgForm报NullInjectorError问题咨询
问题描述
开发了通用错误展示组件ShowErrorComponent,构造函数注入NgForm后在模板驱动表单中可正常显示错误信息,但在响应式表单中使用时,表单无法渲染,抛出如下错误:
ERROR NullInjectorError: R3InjectorError(AppModule)[NgForm -> NgForm -> NgForm]: NullInjectorError: No provider for NgForm! at NullInjector.get (core.mjs:6359:27) at R3Injector.get (core.mjs:6786:33) at R3Injector.get (core.mjs:6786:33) at R3Injector.get (core.mjs:6786:33) at ChainedInjector.get (core.mjs:13769:36) at lookupTokenUsingModuleInjector (core.mjs:3293:39) at getOrCreateInjectable (core.mjs:3338:12) at Module.ɵɵdirectiveInject (core.mjs:10871:12) at NodeInjectorFactory.ShowErrorComponent_Factory [as factory] (show-error.component.ts:9:32) at getNodeInjectable (core.mjs:3523:44)
已在模块中引入ReactiveFormsModule,相关代码如下:
组件代码
export class ShowErrorComponent { // path refering to the form-element @Input('path') controlPath = ''; @Input('name') formName = ''; constructor(private ngForm: NgForm) {} get errorMessages(): string[] | null { const form = this.ngForm.form; const control = form.get(this.controlPath); if (!control || !control.touched || !control.errors) { return null; } return this.getDisplayMessages(control.errors); } .... }
响应式表单使用示例
<form novalidate class="register-form" (ngSubmit)="registerMember(registerForm.value)" [formGroup]="registerForm" > <div formGroupName="personalInfo"> <div class="form-group"> <h3>Personal info:</h3> <div class="input-group mb-3"> <label class="input-group-text" for="gender">Gender</label> <select class="form-select" id="membership" formControlName="gender"> <option value="diverse">Diverse</option> <option value="male">Male</option> <option value="female">Female</option> </select> </div> <app-show-error name="Gender" path="personalInfo.gender"></app-show-error> ... </div> ... </div> </div>
响应式表单初始化代码
constructor(fb: FormBuilder) { this.registerForm = fb.group({ personalInfo: fb.group({ gender: ['diverse'], firstname: ['', [Validators.required]], lastname: ['', [Validators.required]], birthdate: [new Date(), [Validators.required]] }), ... })
报错原因
NgForm是Angular模板驱动表单的专属服务,只有当表单采用模板驱动方式(不绑定[formGroup],依赖Angular自动创建的NgForm实例)时,Angular才会在注入器中提供NgForm的提供者。
而响应式表单通过[formGroup]绑定自定义FormGroup实例时,Angular不会创建NgForm对象,此时组件构造函数注入NgForm就会因找不到对应提供者抛出NullInjectorError。
解决方案
要让组件同时兼容两种表单类型,需替换NgForm注入,改为注入ControlContainer接口——NgForm和响应式表单的FormGroupDirective都实现了该接口,可统一获取表单容器实例。
修改后的组件代码如下:
import { ControlContainer, FormGroup } from '@angular/forms'; export class ShowErrorComponent { @Input('path') controlPath = ''; @Input('name') formName = ''; constructor(private controlContainer: ControlContainer) {} get errorMessages(): string[] | null { const form = this.controlContainer.control as FormGroup; const control = form.get(this.controlPath); if (!control || !control.touched || !control.errors) { return null; } return this.getDisplayMessages(control.errors); } // 保留原错误信息转换逻辑 private getDisplayMessages(errors: any): string[] { const messages: string[] = []; if (errors.required) { messages.push(`${this.formName} 是必填项`); } // 其他错误类型处理逻辑 return messages; } }
修改后组件既能在模板驱动表单中正常工作,也能在响应式表单中获取对应FormGroup实例,不会再出现提供者缺失的错误。
内容的提问来源于stack exchange,提问作者theGoerner
相关产品推荐
相关产品推荐

