2016-03-13 24 views
1

我有一個側面導航組件在許多頁面上使用。這不是一個單頁的網絡應用程序。它動態加載到切換菜單的父組件上。 ContentChild用於獲取子組件的句柄,以便通過設置@input overlayHidden來切換它。問題是ContentChild爲空。@ContentChild爲空的DynamicComponentLoader

打開調試控制檯運行此plunker。從第一頁點擊「Dashboard」,然後從第二頁點擊「切換菜單」查看空指針。

我在做什麼錯?

這是代碼。

import { Component, Input} from 'angular2/core'; 
import { Router } from 'angular2/router'; 

@Component({ 
    selector: 'side-navigation', 
    template: ` 
    <div id="overlay" [hidden]="overlayHidden"> 
    <div id="wrapper"> 
     <nav id="menu" class="white-bg active" role="navigation"> 
      <ul> 
       <li><a href="#">Dashboard</a></li> 
       <li><a href="#">Help & FAQs</a></li> 
       <li><a href="#">Contact Us</a></li> 
       <li><a href="#">Log Out</a></li> 
      </ul> 
     </nav> 
    </div> 
</div> 
` 
}) 
export class SideNavigationComponent { 
    @Input() overlayHidden: boolean; 
} 

import { Component, 
    DynamicComponentLoader, 
    Injector, 
    ContentChild, AfterContentInit 
} from 'angular2/core'; 

import { Router, RouterLink } from 'angular2/router'; 
import { SideNavigationComponent } from './side-navigation'; 

@Component({ 
    selector: 'dashboard', 
    template: ` 
    <side-navigation id="side-navigation"></side-navigation>... 
`, 
directives: [ 
    RouterLink, 
    SideNavigationComponent ] 
}) 
export class DashboardComponent { 
    title = 'Dashboard'; 
    @ContentChild(SideNavigationComponent) 
     sideNavigationComponent: SideNavigationComponent; 

    constructor(private _router: Router, 
     private _dcl: DynamicComponentLoader, 
     private _injector: Injector) { 
     this._router = _router; 
     this._dcl = _dcl; 
     this._injector = _injector; 
     this._dcl.loadAsRoot(
      SideNavigationComponent, 
      '#side-navigation', this._injector); 
    } 

    toggleOverlay() { 
     this.overlayHidden = !this.overlayHidden; 
     this.sideNavigationComponent.overlayHidden = this.overlayHidden; 
    } 
} 

我建立了一個發佈/訂閱的解決方案,工程(除了與覆蓋div的「隱藏」屬性的問題),但我認爲這將是一個簡單的解決方案,如果我能得到它的工作。

+0

您應該使用'loadNextToLocation'或'loadIntoLocation' https://github.com/angular/angular/issues/6223#issuecomment-193908465 –

回答

0

有幾個問題

  • LoadAsRoot不調用變化檢測

目前loadAsRoot()僅用於引導根組件(AppComponent)和輸入不被支持的根組件上。

一種解決方法是在此評論https://github.com/angular/angular/issues/6370#issuecomment-193896657

使用loadAsRoot當需要觸發變化檢測和手動關聯起來的輸入,輸出,注射器,和組分處置功能說明

function onYourComponentDispose() { 
} 
let el = this.elementRef 
let reuseInjectorOrCreateNewOne = this.injector; 
this.componentLoader.loadAsRoot(YourComponent, this.elementRef, reuseInjectorOrCreateNewOne, onYourComponentDispose) 
.then((compRef: ComponentRef) => { 
    // manually include Inputs 
    compRef.instance['myInputValue'] = {res: 'randomDataFromParent'}; 
    // manually include Outputs 
    compRef.instance['myOutputValue'].subscribe(this.parentObserver) 
    // trigger change detection 
    cmpRef.location.internalElement.parentView.changeDetector.ref.detectChanges() 
    // always return in a promise 
    return compRef 
}); 

此評論https://github.com/angular/angular/issues/7453#issuecomment-193138577也有一個鏈接到Plunker示例演示變通辦法

  • DynamicComponentLoader不能在constructor()中使用。此代碼應應該移到ngAfterViewInit()

    this._dcl.loadAsRoot( SideNavigationComponent, '#側導航',this._injector);

  • @Miconyks指出應該使用@ViewChild()而不是@ContentChild()@ContentChild()是傳遞給<ng-content>

+0

@Steve,@Günter - 我們不能使用'ViewChild'來代替ContentChild用於這種用例? – micronyks

+0

你說得對。我也認爲它應該是'ViewChild'。 –

1

內容岡特在他關於@ContentChild,此外,你可能會覺得這個答案已經建議,
As discussed with Günter - see plunker
對不起,我沒有進入深度與你的搶劫者,而不是你想要進一步實現的。但是,如果您要實施ViewChild api,請考慮實施AfterViewInit掛鉤。它也適用於DynamicComponentLoader

相關問題