问题
Common menu usage case
<menu>
<menu-item1></menu-item1>
<menu-item2></menu-item2>
<menu-item3></menu-item3>
</menu>
menu template
<div *ngIf="open$ | async">
<ng-content></ng-content>
</div>
I was suprised to hear that all menu-item*
components (and all their children) will be instantiated despite their presence in DOM and menu
component *ngIf
state. Their OnInit
and AfterViewInit
hooks will be called even if menu has never been opened and OnDestroy
will never fires despite real adding-removing from DOM. Here is a closed issue about this https://github.com/angular/angular/issues/13921 (there is a plnkr with example) and an issue to angular documentation https://github.com/angular/angular.io/issues/3099.
But this issue is still here - how could i do so that menu items will be instantiated only when menu is opened and properly destroyed if closed? All hooks should fire only related to real DOM state.
回答1:
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
You can use
<menu>
<template>
<menu-item1></menu-item1>
<menu-item2></menu-item2>
<menu-item3></menu-item3>
<template>
</menu>
@Component({
selector: 'menu',
template: `
<div *ngIf="open$ | async">
<template [ngTemplateOutlet]="templateRef"></template>
</div>
`
})
class MenuComponent {
@ContentChild(TemplateRef) templateRef:TemplateRef;
}
You can also pass context to ngTemplateOutlet
(there are some answers that show how to do that, I don't have time just not to look them up)
回答2:
This is an exemple using ngTemplateOutlet
import {Component, NgModule} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
@Component({
selector: 'my-app',
template: `
<template #templateRef let-label="label" let-url="url">
<div><a href="{{url}}">{{label}}</a></div>
</template>
<div [ngTemplateOutlet]="templateRef" [ngOutletContext]="menu[0]"></div>
<div [ngTemplateOutlet]="templateRef" [ngOutletContext]="menu[1]"></div>
`
})
export class App {
menu:any = [{
"id": 1,
"label": "AngularJS",
"url": "http:\/\/www.learn-angular.fr\/angularJS"
}, {
"id": 2,
"label": "Angular",
"url": "http:\/\/www.learn-angular.fr\/angular"
}];
constructor() {}
}
来源:https://stackoverflow.com/questions/41652919/instantiate-transcluded-components-depending-on-their-dom-state-in-angular-2