简体   繁体   中英

Lifecycle ngDestroy in Angular 9 with ngIf and ngContent

I implemented some basic stepper (tabs) and used *ngIf for hiding, not active tab content. But if I use the component in inactive tabs when the page was loaded component calls onInit(and not call onDestroy on leave) even if I not switching to this tab.

Attaching stackblitz to reproduce - link . What am I missing?

AR: ngOnInit calls even if the second tab wasn't activated. And ngOnDestroy should not call on leaving this tab.

ER: ngOnInit not calls when first tabs rendered. And ngOnDestroy should call on leaving this tab.

Your assumption is wrong. If you look at your template from your AppComponent :

<stepper>
  <step>
    some data
  </step>
  <step>
    <app-test></app-test>
  </step>
</stepper>

You clearly see the <step> and <app-test> both be there. There is no *ngIf logic wrapped around them, so they will always be 'initialized'. Not necessarily displayed, but the component instances do exist, because they are defined in the parent template, not in the ng-content . The <ng-content> is basically just a tag from which you can move an element from a parent component to a child component. However the context of the component stays in the parent, and the displaying of it should somehow be controlled by the parent.

There is a way to fix this. On way is to make your StepComponent a structural directive.

@Directive({
  selector: '[step]'
})
export class StepDirective {
  active?: boolean;

  constructor(readonly tr: TemplateRef<any>) {}
}

This changes your template to:

<stepper>
  <ng-container *step>
    some data
  </ng-container>

  <app-test *step></app-test>
</stepper>

Now the two steps are part of templates, and won't be initialized until you explicitly tell it to do so. For this we need to update the stepper.component.ts .:

(only showing the necessary updates)

@ContentChildren(StepDirective)
tabs: QueryList<StepDirective>;

Now all that's left is to use the *ngTemplateOutlet directive inside your stepper.component.html :

<div class="tab-body">
  <ng-template [ngTemplateOutlet]="selectedTab.tr"></ng-template>
</div>

This controls the initialization of the templates and changes to what tab is active at the moment.

working example

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM