4

I have an expander that uses content projection. The expander content is wrapped into an *ngIf (for performance optimization). Unfortunately I realized that all my directives within the expandable get initialized at the very application start, even though the expandable is initially closed.

My directive must not initialize before the expandable is actually opened. So either I need some kind of initialization delay, or a hook that triggers when the directive is actually rendered.

An example code (Plunker here: https://plnkr.co/edit/R84AXZheAtZYLRmeSfkm?p=preview):

@Component({
  selector: 'my-app',
  template: `
    <some-component>
      Projected content <div some-directive></div>
    </some-component>
  `,
})
export class App {}


//************* Component that uses content projection *************

@Component({
  selector: 'some-component',
  template: `
    <button (click)="showBody=!showBody">Toggle Content</button>
    <div *ngIf="showBody">
      <ng-content></ng-content>
    </div>
  `,
})
export class SomeComponent {
  constructor() {}
  private showBody = false;
}

//************* Directive that is set within an ng-if *************
@Directive({
  selector: '[some-directive]',
})
export class SomeDirective {
  constructor() {
  }

  ngOnInit() {
    document.body.append('This should not be executed when the content is not visible');
  }
}

A Plunker can be found here: https://plnkr.co/edit/R84AXZheAtZYLRmeSfkm?p=preview

Claies
  • 22,124
  • 4
  • 53
  • 77
Badudel
  • 41
  • 3
  • 1
    don't use the angularjs tag for questions relating to angular2, unless your question relates to both frameworks, like migration questions, for example. These are two different frameworks, despite having a shared name. – Claies Nov 24 '16 at 20:51

1 Answers1

0

update Angular 5

ngOutletContext was renamed to ngTemplateOutletContext

See also https://github.com/angular/angular/blob/master/CHANGELOG.md#500-beta5-2017-08-29

original

That is expected behavior. You can have projected content without <ng-content> and query it using @ContentChildren().

You need another strategy. For example pass the content as template and use ngTemplateOutlet to insert the content

See also How to repeat a piece of HTML multiple times without ngFor and without another @Component

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Thanks for your response. Is there some kind of hook that I can use within the directive in order to get notified when it gets rendered? – Badudel Nov 25 '16 at 08:16
  • The directive itself gets rendered just after `ngOnInit()`. I'm not sure if `ngAfterViewInit()` is called for a directive, but `ngAfterContentInit()` is called and that should do. – Günter Zöchbauer Nov 25 '16 at 09:03