No provider for TemplateRef’ Explained.

piotr szybicki
12 developer labors

--

Recently I started answering questions on stack overflow. I found this very rewarding as well as useful to retain the knowledge. As various projects or job changes may lead us in to a different avenues of massive field, that is programming.

I stumbled upon question that gave me pause. The error message read: ‘ No provider for TemplateRef’. I was interested. Especially that under a comment one of the guru in Angular community wrote: ‘ You missed basic knowledge about TemplateRef’. Which meant that I also lack some basic knowledge in that area. I didn’t like that at all. So i started my research. In this short article I will use directive (both structural and regular) to illustrate my point.

So we all know the structural directives. We use them all the time *ngIf, *ngFor, and maybe not so often used *ngSwitch. Notice something very interesting. All those have the * in front of them. That star is used to do something very specific. It turn this:

<div *directive="3000">Tesla was robbed !!!!</div>

into this:

<!--bindings={
"ng-reflect-directive-somevariable": "3000"
}-->
<div>Tesla was robbed !!!!</div>

with and intermediate stage:

<ng-template [SomeVariable]="3000">   
<div>Tesla was robbed !!!!</div>
</ng-template>

And this is declaration of our directive.

@Directive({
selector: '[appStructural]'
})
export class StructuralDirective {
constructor(
private templateRef: TemplateRef<any>,
private viewContainerRef: ViewContainerRef
){}
@Input('appStructural')
set someVariable(time: ViewContainerRef) {
this.viewContainerRef.createEmbeddedView(this.templateRef);
}
}

The line in bold is very important without it we will not see our component render on the DOM tree. And on the subject of this article. This is the only way we can inject a TemplateRef via the constructor. If we try to do this for the components or directives we will get the error NullInjectorError: No provider for TemplateRef!. This makes sense so far? Because smart or dumb person could ask. Ok if angular desugars the tag with the structural directives in to that <compoent-tag> and <template> then if I place my component inside <ng-template> manually

<ng-template>   
<app-component></app-component>
</ng-template>

I should be able to inject, the TemplateRef into that component. Sorry but no. That component is sill created by the View component factory and you can access it via ElementRef. More on this:

--

--

piotr szybicki
12 developer labors

Piotr Szybicki’s, Programmer, Java Developer, ML Entusiast