如何访问父组件提供的、TemplateRef内部指令所需的Service?
如何让传入的TemplateRef获取父组件提供的非ViewContent内的Service?
问题原因
你遇到的NullInjectorError核心原因是TemplateRef的注入上下文绑定问题:
你在RootComponent中定义的<ng-template>,它的依赖注入上下文默认绑定的是RootComponent的注入器,而非最终渲染它的AppComponent的注入器。当TestDirective尝试注入SomeService时,会沿着RootComponent的注入器链查找,自然找不到AppComponent专属提供的服务实例。
解决方案
方法一:通过ngTemplateOutletInjector指定注入器
这是Angular官方推荐的标准方案,直接在渲染模板时指定使用AppComponent的注入器:
- 在
AppComponent中注入并暴露自身的Injector:
import { Component, Input, TemplateRef, Injector } from '@angular/core'; @Component({ selector: 'app-component', template: ` <ng-container [ngTemplateOutlet]="itemTemplate" [ngTemplateOutletInjector]="injector" ></ng-container> `, changeDetection: ChangeDetectionStrategy.OnPush, providers: [SomeService], }) export class AppComponent { @Input() itemTemplate: TemplateRef<unknown> | null = null; constructor(public injector: Injector) {} // 注入当前组件的注入器并暴露 }
修改后,模板在AppComponent内渲染时,会使用AppComponent的注入器解析依赖,TestDirective就能成功获取SomeService实例。
方法二:自定义嵌入式视图(进阶场景)
如果需要更精细的上下文控制,可以在AppComponent中利用ViewContainerRef手动创建嵌入式视图并指定注入器,仅适合特殊场景:
import { Component, Input, TemplateRef, ViewContainerRef, Injector } from '@angular/core'; @Component({ selector: 'app-component', template: `<div #container></div>`, changeDetection: ChangeDetectionStrategy.OnPush, providers: [SomeService], }) export class AppComponent { @Input() set itemTemplate(template: TemplateRef<unknown> | null) { if (template && this.container) { this.container.clear(); // 使用当前组件的注入器创建视图 this.container.createEmbeddedView(template, null, { injector: this.injector }); } } constructor( private container: ViewContainerRef, private injector: Injector ) {} }
验证结果
采用第一种方案后,TestDirective的构造函数将成功注入AppComponent提供的SomeService,不再抛出NullInjectorError。
内容的提问来源于stack exchange,提问作者coltrane
相关产品推荐
相关产品推荐

