TimTheEnchanter
TimTheEnchanter

Reputation: 3671

TemplateRef constructor injection No provider for TemplateRef

Maybe I'm fundamentally misunderstanding something, but I'm trying to get a TemplateRef pointing to my Component's template (simply 'Hello' in the bare-bones example below). I've stripped my code down to the bare minimum to try to identify the problem:

import { Component, TemplateRef} from '@angular/core';
@Component({
  selector: 'app-root',
  template: `Hello`,
  styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {
  constructor(private tr: TemplateRef<any>) {}
}

This doesn't actually "do" anything as I've removed all functionality, but I would have expected this to work. When I run this code, I get an error: No provider for TemplateRef and yet I see examples on SO and elsewhere where this apparently works. What am I missing?

Angular 4.2.4

Thanks.

Upvotes: 3

Views: 3596

Answers (1)

piotr szybicki
piotr szybicki

Reputation: 1602

I know it's old but let me answer that as I've struggled with that very same question for the past couple of days. The only way you can inject the TemplateRef in to your code, via constructor, is when you are working inside the structural directive (the one with the star *). You see all the components are created using View Factory and therefor they are created as Host View-s. Even if you warp them in the tag you can't inject TemplateRef into a component.

Structural directives are different as they from this:

<div *myDirective="1">Tesla was robbed !!!!</div>

Become this:

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

To be renderd like this:

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

And because that are created as embedded views you can inject template. If you think about it it makes sens. Because initially all that appears in the DOM is that html comment. You have to tell angular to render the <div> tag. And you do that:

 this.viewContainerRef.createEmbeddedView(this.templateRef);

*ngIf works like that. Without the concept of structural directives you would have to create conditional logic inside your components. And manually add or remove view-s that you need. You can do that in angular but it is messier.

Upvotes: 7

Related Questions