0

Component with ng-template

@Component({
  template: `
    <div>Hello Component is here!</div>

    <ng-template #cmp_anchor>
      <div>Template content</div>
    </ng-template>
  `,
})
export class HelloComponent {}

When rendered with ngTemplateOutlet there is no access to ng-template

@Component({
  selector: 'my-app',
  template: `
    <ng-container *ngComponentOutlet="helloComponent"></ng-container>

    <ng-container
      [ngTemplateOutlet]="cmpTemplateRef">
    </ng-container>
  `
})
export class AppComponent  {
  public helloComponent = HelloComponent;

  @ContentChild('cmp_anchor', {read: TemplateRef}) cmpTemplateRef: TemplateRef<any>;
}

Example code on: https://stackblitz.com/edit/angular-ng-component-outlet-with-ng-template?embed=1&file=src/app/app.component.ts

critrange
  • 5,652
  • 2
  • 16
  • 47

1 Answers1

1

That's indeed not possible. The @ContentChild in a component looks at the content inside the components tag. For instance: <my-cmp><ng-template #cmp_anchor></ng-template></my-cmp>, would return a template if you set the @ContentChild on the MyComponent class.

There is no direct way for accessing the ng-template from a component projected using the ngComponentOutlet. You cannot even access the HelloComponent instance.

You can do a private access to the _componentRef of the ngComponentOutlet instance, but that's a bit hacky. I suggest you go back to the drawing board, or rephrase your question with what greater issue you are trying to solve with your request. Anyways, to make it work, you can (but shouldn't) do the following:

@Component({
  template: `
    <div>Hello Component is here!</div>

    <ng-template #cmp_anchor>
      <div>Template content</div>
    </ng-template>
  `,
})
export class HelloComponent  {
  @ViewChild('cmp_anchor', {read: TemplateRef})
  cmpTemplateRef: TemplateRef<any>;
}

@Component({
  selector: 'my-app',
  template: `
    <ng-container *ngComponentOutlet="helloComponent"></ng-container>

    <ng-container
      [ngTemplateOutlet]="$any(ng)?._componentRef.instance.cmpTemplateRef">
    </ng-container>
  `
})
export class AppComponent  {
  public helloComponent = HelloComponent;

  @ViewChild(NgComponentOutlet) ng: NgComponentOutlet;
}

working example

If it's still something you think you need to do this way, you can always write your own structural directive based upon the ngComponentOutlet directive. From there you can expose all kind of things from whatever is passed into the outlet directive

Poul Kruijt
  • 69,713
  • 12
  • 145
  • 149
  • This produces compile error in angular 9+ where ivy is used – Aleksandar Petrovic Sep 22 '20 at 12:52
  • @AleksandarPetrovic it being sort of a hack, I can imagine it does. I've added a `$any()` around the `ng` in the template. That should fix that error. Nevertheless, I don't think you should use that solution, as I said before – Poul Kruijt Sep 22 '20 at 13:37