通过ngTemplateOutletInjector传入模板的Injector与组件获取的不一致问题
解决NgTemplateOutletInjector无法提供NgForm的问题
问题原因
- 你创建的自定义Injector是独立根注入器,未继承模态框容器组件的注入上下文,导致模板内组件无法通过注入链获取NgForm实例。
- 服务中直接赋值
component.injector时,容器组件的form(通过ViewChild查询)可能尚未初始化——ViewChild的查询要等到组件AfterViewInit生命周期阶段才会完成。
修复方案
1. 让自定义Injector继承组件注入器
修改模态框服务的open方法,创建Injector时指定parent为容器组件自身的注入器,确保注入链能继承组件级提供者:
open(type: ModalType, template: TemplateRef<any>, model?: any) { let ref = this.modal.open(ModalContainerComponent); let component = ref.componentInstance as ModalContainerComponent; component.tRef = template; // 关键:传入组件自身注入器作为父级,继承上下文 component.injector = Injector.create({ providers: [ { provide: NgForm, useFactory: () => component.form } ], parent: component.injector }); }
2. 确保NgForm实例就绪后再渲染模板
在ModalContainerComponent中,等到AfterViewInit生命周期再标记初始化完成,避免模板渲染时form还未被查询到:
import { Component, ViewChild, AfterViewInit, Injector } from '@angular/core'; import { NgForm } from '@angular/forms'; @Component({ // 组件元数据 }) export class ModalContainerComponent implements AfterViewInit { @ViewChild('form') form!: NgForm; tRef!: TemplateRef<any>; injector?: Injector; initialized = false; m?: any; ngAfterViewInit(): void { // 确认form已获取后,允许模板渲染 this.initialized = true; } commit() { // 提交逻辑 } }
3. 保持模板条件渲染逻辑
模板中的条件判断确保只有当所有依赖都就绪后才渲染模板出口,无需修改:
<form #form="ngForm" (ngSubmit)="commit()" [ngFormOptions]="{ updateOn: 'change' }"> <ng-container *ngIf="initialized && tRef && m && injector"> <ng-container *ngTemplateOutlet="tRef; context: { $implicit: { m } }" [ngTemplateOutletInjector]="injector"></ng-container> </ng-container> </form>
补充说明
NgForm是绑定在<form>元素上的组件级提供者,只有当自定义Injector继承组件的注入上下文时,模板内的组件才能通过注入链找到它。- 若后续仍有问题,可考虑在
ModalContainerComponent内部创建Injector并通过回调通知服务,而非在服务中直接创建,这样能更精准地控制生命周期时机。
内容的提问来源于stack exchange,提问作者RTD
相关产品推荐
相关产品推荐

