angular: Transcluded components hooks works incorrectly with upper `*ngIf` state
I’m submitting a … (check one with “x”)
[ x ] bug report
[ ] feature request
[ ] support request
Current behavior
Transcluded via ng-content
components OnInit
and AfterViewInit
hooks are triggered despite parent component ngIf
state. OnDestroy
hook does not triggered on removing from DOM.
Expected behavior Hooks should be triggered only when component really are added/removed from DOM.
Minimal reproduction of the problem with instructions Plnkr http://plnkr.co/edit/RkOXyEtvMNoSNLeAh8Jf?p=preview
MenuItemComponent
OnInit
and AfterViewInit
hooks triggered despite MenuComponent
ngIf
false value and OnDestroy
never fires despite component removing from DOM.
- Angular version: 2.4.3
update
added one more plnkr - anything inside <menu>
component will be initialized with all children despite it never will be added to dom due to closed menu. Comment bellow https://github.com/angular/angular/issues/13921#issuecomment-272589159
http://plnkr.co/edit/2aaRtK3rppO9Qi8zWaWi?p=preview
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Comments: 26 (19 by maintainers)
I want to add this is definitely not expected and if not known and handled can cause huge performance issues in instances like tabs.
Looks like solution is to use
<template>
around menu items andTemplateRef
/[ngTemplateOutlet]
in menu component, thx to Günter http://stackoverflow.com/a/41655566/5803093There is a big lack in ng2 documentation on this theme 😦
Also as i understand
AfterViewInit
guarantees that component is added to DOM here that is wrong with this transclusion behavior.@montella1507 … yep, you are right in that. Some of those third party libs are not able to work on the nodes which are not in DOM. Then you have to add some your custom logic to control what to invoke and when … in relation if the node is or isn’t in DOM.
@montella1507 As “Angular application can be entirely bootstrapped in a detach element”, any component MUST NOT assume their host elements being mounted in
document
(if wanted to be robust). If your case require it being attached, then the component should guard that by itself.@montella1507 … what is exactly component X?
Generally … if the template
abc.component.html
of the component ABC contains …then
<div *ngIf="true">
would mean creating a new instance of component Y and inserting it to the DOM and with<div *ngIf="false">
it is reversed.But with transcluded content, like …
the instance of component Y is created in the same moment when the instance of the component ABC and it is kept regardless of the conditional logic and
*ngIf
applied on<ng-content>
inside the template of ABC. All of that (generated JS code) is defined by Angular compiler when HTML templates are compiled (AOT / JIT) and not during run-time.@mhevery so for any component there is no guarantees that init/destroy hooks will be related to component DOM existing state and depends on outer context that cant be detected from this component?
@mhevery em… but what with menu/tabs components if their items depends on some data that should be updated before menu is opened and has a lot of handlers in
OnInit
AfterViewInit
OnDestroy
hooks? Why this components should be init when they are not needed and should not do anything, that is controlled by upperngIf
.