为何添加LoaderDirective时出现“No provider for _TemplateRef found”错误?
为何添加LoaderDirective时会出现“No provider for _TemplateRef found”错误?
错误原因
这个错误的核心是**TemplateRef的注入上下文不匹配**:
TemplateRef是Angular用于表示内嵌模板的类,它只能在特定上下文被注入:要么指令直接作用于<ng-template>标签,要么通过Angular的*语法糖(结构型指令的写法)自动将宿主元素包装为<ng-template>。- 你的指令直接通过
inject(TemplateRef<any>)获取实例,但如果使用时只是把它当作普通属性指令(比如<div appLoader [hidden]="true">...</div>),Angular找不到对应的TemplateRef提供者,就会抛出这个错误。
解决方案
根据你的业务需求,有两种可行的修复方式:
方案1:改为结构型指令(推荐,匹配你的视图创建/销毁逻辑)
结构型指令通过*语法糖使用,Angular会自动将宿主元素转换为<ng-template>,此时就能正常注入TemplateRef和ViewContainerRef。
调整指令代码(优化Input命名以符合结构型指令习惯):
import { Directive, Input, OnChanges, SimpleChanges, inject, TemplateRef, ViewContainerRef } from '@angular/core'; @Directive({ selector: '[appLoader]' }) export class LoaderDirective implements OnChanges { // 将Input与指令选择器同名,方便*语法使用 @Input() appLoader: boolean | null = false; private template = inject(TemplateRef<any>); private viewContainerRef = inject(ViewContainerRef); ngOnChanges(changes: SimpleChanges): void { if (changes['appLoader'].currentValue) { this.viewContainerRef.clear(); } else { this.viewContainerRef.createEmbeddedView(this.template); } } }
使用方式(注意*前缀):
<!-- 当isLoading为true时隐藏内容,为false时显示 --> <div *appLoader="isLoading">加载完成的内容</div>
方案2:改为属性型指令(仅控制元素显隐,不销毁视图)
如果你的需求只是简单控制元素显示/隐藏,不需要创建销毁视图实例,可以放弃注入TemplateRef,直接操作宿主元素:
import { Directive, Input, OnChanges, SimpleChanges, inject, ElementRef } from '@angular/core'; @Directive({ selector: '[appLoader]' }) export class LoaderDirective implements OnChanges { private el = inject(ElementRef); @Input() hidden: boolean | null = false; ngOnChanges(changes: SimpleChanges): void { const isHidden = changes['hidden'].currentValue; this.el.nativeElement.hidden = isHidden; // 或者用display样式:this.el.nativeElement.style.display = isHidden ? 'none' : ''; } }
使用方式(作为普通属性指令):
<div appLoader [hidden]="isLoading">内容</div>
内容的提问来源于stack exchange,提问作者MOE S NUA
相关产品推荐
相关产品推荐

