2

I am facing a strange bug with a ng-content wrapped in a ng-template.

Let's say I have a component inner-component which I display within a outer-component:

<ng-container *ngIf="condition" [ngTemplateOutlet]="test"></ng-container>
<ng-template #test>
    <inner-component></inner-component>
</ng-template>

If condition=false, then, as expected, my inner-component is never created by Angular (when debugging, ngOnInit() is never called).

Now, if instead I have my outer component as:

<ng-container *ngIf="condition" [ngTemplateOutlet]="test"></ng-container>
<ng-template #test>
    <ng-content></ng-content>
</ng-template>

and, still with condition=false, I write:

<outer-component>
    <inner-component></inner-component>
</outer-component>

Then, to my surprise, the inner-component is created, even if it is never rendered. This is a problem for me because the inner-component (a 3rd party component which I can't modify) really does need to be created when it is rendered in the app.

Can you think of a workaround I could use on the outer component to avoid creating the ng-content, (while still using transclusion obviously - the first solution is not an option).

Eric Leibenguth
  • 4,167
  • 3
  • 24
  • 51
  • perhafs you wrote in .ts condition="false" (a string) -well, generally this happens when received data from a service and is a string- or you has a template reference variable called condition – Eliseo Sep 09 '20 at 17:12
  • Oh, I get what you're doing now! You don't want the `inner` component to be initialized on the outside of outer, but from within the `outer-component`'s template by using a conditional around `ng-content`. – hyperdrive Sep 09 '20 at 17:17
  • Yes, after much head-scratching, I think this is actually the same problem as described here: https://stackoverflow.com/questions/44929726/angular4-ng-content-gets-built-when-ngif-is-false except I cannot use the proposed solution... – Eric Leibenguth Sep 09 '20 at 17:37

1 Answers1

1

You could move the template to the parent component.

<app-outer>
    <ng-template #test>
        <app-inner></app-inner>
    </ng-template>
</app-outer>

And in your outerComponent get a child reference to the template

@ContentChild('test') testTemplate: TemplateRef<ElementRef>;

Outer html

<ng-container *ngIf="condition" [ngTemplateOutlet]="testTemplate"></ng-container>

Stackblitz

hyperdrive
  • 1,786
  • 5
  • 19
  • 33
  • Hmm, no my inner-component is in the right place, within the `test` template. This `test` template is supposed to be rendered within the first ng-container if the condition is `true` – Eric Leibenguth Sep 09 '20 at 16:34
  • Facepalm. Update answer, I think this is why. – hyperdrive Sep 09 '20 at 16:39
  • Your answer is correct, but I wish there were a way to keep the current API for my outer-component (that is avoid the ng-template wrapping the inner-component) – Eric Leibenguth Sep 09 '20 at 17:40
  • @EricLeibenguth Couple things you could also consider are dynamic component loading, or making custom structural directives. I've struggled with this same issue before also. – hyperdrive Sep 09 '20 at 17:55