Angular4 ng-content gets built when ngIf is false

By doing this:

<my-wrapper *ngIf="false">
    <my-component></my-component>
</my-wrapper>

You are not calling MyComponent component, because the *ngIf is false. that means, that not calling it you are not instancing it and, therefore, not passing through its ngOnInit. And that's why you are not getting the console log.

By doing this:

<ng-container *ngIf="false">
    <ng-content></ng-content>
</ng-container>

You are inside the component, you are just limiting what to render in your template, but you already instanced your component and, therefore, you passed through your ngOnInit and you get your console log done.

If, you want to limit something (component call with selector or a ng-content or even a div) until you have some data available, you can do the following:

datasLoaded: Promise<boolean>;

this.getData().subscribe(
       (data) => {
            this.datasLoaded = Promise.resolve(true); // Setting the Promise as resolved after I have the needed data
       }
);

And in your template:

<ng-container *ngIf="datasLoaded | async">
   // stuff here
</ng-container>

Or:

<my-component *ngIf="datasLoaded | async">
   // Didn't test this one, but should follow the same logic. If it doesn't, wrap it and add the ngIf to the wrapper
</my-component>

Based on the comment of @nsinreal I found an answer. I find it to be a bit abstruse, so I'm trying to post it here:

The answer is to work with ng-template and *ngTemplateOutlet.

In the my-wrapper component, set up the template like this (my-wrapper.component.html):

<div (click)="toggleDetail()">Click for more</div>
<div *ngIf="showDetail" [hidden]="!isInitialized">
    <ng-container *ngTemplateOutlet="detailRef"></ng-container>
</div>

Note, that the [hidden] there is not really necessary, it hides the "raw" template of the child until it decides it is done loading. Just make sure, not to put it in a *ngIf, otherwise the *ngTemplateOutlet will never get triggered, leading to nothing happening at all.

To set the detailRef, put this in the component code (my-wrapper.component.ts):

import { ContentChild, TemplateRef } from '@angular/core';

@Component({ ... })
export class MyWrapperComponent {
    @ContentChild(TemplateRef) detailRef;

    ...
}

Now, you can use the wrapper like this:

<my-wrapper>
    <ng-template>
        <my-component></my-component>
    </ng-template>
</my-wrapper>

I am not sure, why it needs such complicated "workarounds", when it used to be so easy to do this in AngularJS.