Instantiate transcluded components depending on their DOM state in angular 2

你说的曾经没有我的故事 提交于 2019-12-06 19:16:40

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!