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

1 Answer 1

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

Sign up to request clarification or add additional context in comments.

2 Comments

This produces compile error in angular 9+ where ivy is used
@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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.