2016-09-28 27 views
2

我試圖通過@ViewChild()裝飾調用childMethod從父組件的子組件內的一個很簡單的例子。不幸的是,ViewChild變量總是未定義的。Angular2查看兒童未定義的錯誤

輔元件

import {Component, Input, Output, EventEmitter} from '@angular/core'; 
import {Character} from "../models/character"; 

@Component({ 
    selector: 'my-character', 
    templateUrl: 'app/components/my.character.component.html' 
}) 
export class MyCharacter { 
    @Output() changed: EventEmitter<any> = new EventEmitter(); 
    @Input() character: Character; 

    selectedCharacter: Character; 

    select(selectedCharacter: Character) { 
     this.selectedCharacter = selectedCharacter; 
     this.changed.emit(selectedCharacter); 
    }; 

    childMethod() { 
     console.log('This method is called from the parent component via ViewChild'); 
    }; 
} 

父組件

import { Component, ViewChild, AfterViewInit } from '@angular/core'; 
import { Character } from '../models/character'; 
import { MyCharacter } from "../components/my.character.component"; 

@Component({ 
    selector: 'character-list', 
    templateUrl: 'app/components/character.list.component.html', 
    directives: [ MyCharacter ] 
}) 
export class CharacterList implements AfterViewInit{ 
    selectedCharacter: Character; 

    @ViewChild(MyCharacter) myChar:MyCharacter; 

    ngOnInit() { 
     console.log('on init'); 
    }; 

    ngAfterViewInit() { 
     console.log('after init'); 
    }; 

    characters = [ 
     new Character(1, 'Han Solo'), 
     new Character(2, 'Luke Skywalker'), 
     new Character(3, 'BB-8'), 
     new Character(4, 'Rey') 
    ]; 
    select(selectedCharacter: Character) { 
     this.selectedCharacter = selectedCharacter; 
     this.myChar.childMethod(); 
    } 

    changed (event: any) { 
     console.log('Hello! There is a change in the item.'); 
    } 
} 

父組件的HTML

<h2>Characters</h2> 

<ul> 
    <li *ngFor="let character of characters" (click)="select(character)"> 
     {{character.name}} 
    </li> 
</ul> 

<my-character *ngIf="selectedCharacter" [character]="selectedCharacter" (changed)="changed($event)"></my-character> 

錯誤,當我調用點擊方法

core.umd.js:3462 EXCEPTION: Error in app/components/character.list.component.html:3:45 caused by: Cannot read property 'childMethod' of undefinedErrorHandler.handleError @ core.umd.js:3462next @ core.umd.js:6924schedulerFn @ core.umd.js:6172SafeSubscriber.__tryOrUnsub @ Subscriber.ts:238SafeSubscriber.next @ Subscriber.ts:190Subscriber._next @ Subscriber.ts:135Subscriber.next @ Subscriber.ts:95Subject.next @ Subject.ts:61EventEmitter.emit @ core.umd.js:6164onError @ core.umd.js:6388onHandleError @ core.umd.js:6263ZoneDelegate.handleError @ zone.js:207Zone.runGuarded @ zone.js:113NgZoneImpl.runInnerGuarded @ core.umd.js:6271NgZone.runGuarded @ core.umd.js:6504outsideHandler @ platform-browser.umd.js:1990ZoneDelegate.invokeTask @ zone.js:236Zone.runTask @ zone.js:136ZoneTask.invoke @ zone.js:304 
core.umd.js:3464 ORIGINAL EXCEPTION: Cannot read property 'childMethod' of undefinedErrorHandler.handleError @ core.umd.js:3464next @ core.umd.js:6924schedulerFn @ core.umd.js:6172SafeSubscriber.__tryOrUnsub @ Subscriber.ts:238SafeSubscriber.next @ Subscriber.ts:190Subscriber._next @ Subscriber.ts:135Subscriber.next @ Subscriber.ts:95Subject.next @ Subject.ts:61EventEmitter.emit @ core.umd.js:6164onError @ core.umd.js:6388onHandleError @ core.umd.js:6263ZoneDelegate.handleError @ zone.js:207Zone.runGuarded @ zone.js:113NgZoneImpl.runInnerGuarded @ core.umd.js:6271NgZone.runGuarded @ core.umd.js:6504outsideHandler @ platform-browser.umd.js:1990ZoneDelegate.invokeTask @ zone.js:236Zone.runTask @ zone.js:136ZoneTask.invoke @ zone.js:304 
core.umd.js:3467 ORIGINAL STACKTRACE:ErrorHandler.handleError @ core.umd.js:3467next @ core.umd.js:6924schedulerFn @ core.umd.js:6172SafeSubscriber.__tryOrUnsub @ Subscriber.ts:238SafeSubscriber.next @ Subscriber.ts:190Subscriber._next @ Subscriber.ts:135Subscriber.next @ Subscriber.ts:95Subject.next @ Subject.ts:61EventEmitter.emit @ core.umd.js:6164onError @ core.umd.js:6388onHandleError @ core.umd.js:6263ZoneDelegate.handleError @ zone.js:207Zone.runGuarded @ zone.js:113NgZoneImpl.runInnerGuarded @ core.umd.js:6271NgZone.runGuarded @ core.umd.js:6504outsideHandler @ platform-browser.umd.js:1990ZoneDelegate.invokeTask @ zone.js:236Zone.runTask @ zone.js:136ZoneTask.invoke @ zone.js:304 
core.umd.js:3468 TypeError: Cannot read property 'childMethod' of undefined 
    at CharacterList.select (character.list.component.ts:31) 
    at DebugAppView._View_CharacterList1._handle_click_0_0 (CharacterList.ngfactory.js:157) 
    at eval (core.umd.js:9698) 
    at eval (platform-browser.umd.js:1877) 
    at eval (platform-browser.umd.js:1990) 
    at ZoneDelegate.invoke (zone.js:203) 
    at Object.onInvoke (core.umd.js:6242) 
    at ZoneDelegate.invoke (zone.js:202) 
    at Zone.runGuarded (zone.js:110) 
    at NgZoneImpl.runInnerGuarded (core.umd.js:6271)ErrorHandler.handleError @ core.umd.js:3468next @ core.umd.js:6924schedulerFn @ core.umd.js:6172SafeSubscriber.__tryOrUnsub @ Subscriber.ts:238SafeSubscriber.next @ Subscriber.ts:190Subscriber._next @ Subscriber.ts:135Subscriber.next @ Subscriber.ts:95Subject.next @ Subject.ts:61EventEmitter.emit @ core.umd.js:6164onError @ core.umd.js:6388onHandleError @ core.umd.js:6263ZoneDelegate.handleError @ zone.js:207Zone.runGuarded @ zone.js:113NgZoneImpl.runInnerGuarded @ core.umd.js:6271NgZone.runGuarded @ core.umd.js:6504outsideHandler @ platform-browser.umd.js:1990ZoneDelegate.invokeTask @ zone.js:236Zone.runTask @ zone.js:136ZoneTask.invoke @ zone.js:304 
core.umd.js:3471 ERROR CONTEXT:ErrorHandler.handleError @ core.umd.js:3471next @ core.umd.js:6924schedulerFn @ core.umd.js:6172SafeSubscriber.__tryOrUnsub @ Subscriber.ts:238SafeSubscriber.next @ Subscriber.ts:190Subscriber._next @ Subscriber.ts:135Subscriber.next @ Subscriber.ts:95Subject.next @ Subject.ts:61EventEmitter.emit @ core.umd.js:6164onError @ core.umd.js:6388onHandleError @ core.umd.js:6263ZoneDelegate.handleError @ zone.js:207Zone.runGuarded @ zone.js:113NgZoneImpl.runInnerGuarded @ core.umd.js:6271NgZone.runGuarded @ core.umd.js:6504outsideHandler @ platform-browser.umd.js:1990ZoneDelegate.invokeTask @ zone.js:236Zone.runTask @ zone.js:136ZoneTask.invoke @ zone.js:304 
core.umd.js:3472 DebugContext {_view: _View_CharacterList1, _nodeIndex: 0, _tplRow: 3, _tplCol: 45}ErrorHandler.handleError @ core.umd.js:3472next @ core.umd.js:6924schedulerFn @ core.umd.js:6172SafeSubscriber.__tryOrUnsub @ Subscriber.ts:238SafeSubscriber.next @ Subscriber.ts:190Subscriber._next @ Subscriber.ts:135Subscriber.next @ Subscriber.ts:95Subject.next @ Subject.ts:61EventEmitter.emit @ core.umd.js:6164onError @ core.umd.js:6388onHandleError @ core.umd.js:6263ZoneDelegate.handleError @ zone.js:207Zone.runGuarded @ zone.js:113NgZoneImpl.runInnerGuarded @ core.umd.js:6271NgZone.runGuarded @ core.umd.js:6504outsideHandler @ platform-browser.umd.js:1990ZoneDelegate.invokeTask @ zone.js:236Zone.runTask @ zone.js:136ZoneTask.invoke @ zone.js:304 
zone.js:140 Uncaught Error: Error in app/components/character.list.component.html:3:45 caused by: Cannot read property 'childMethod' of undefined 

任何澄清會有所幫助我得到。

回答

4

這是罪魁禍首:

*ngIf="selectedCharacter" 

ngIf將阻止ViewChild被實例化,這是爲時已晚。您可以將它移動到MyCharacter的模板中,以在父組件中引用ViewChild引用,而不會更改您應用的任何行爲。

+0

非常感謝。我不明白'爲什麼'背後它:(雖然是可能的在Angular 1.x –

+2

嚴我沒有AngularJS 1.x的經驗,所以無法證實它。但在這裏,當你使用'* ngIf'和你的條件是'假',那麼DOM不會在那裏,並且你沒有引用任何東西。當你改變條件('selectedCharacter')來啓用這個DOM時,它會用Angular2來實例化你的'ViewChild',這就是爲什麼你不能立即調用它的函數,就像你在函數中做的那樣。 –

+0

你搖滾!!!謝謝哈利!這是確切的原因,我手動將ngIf設置爲true並檢查,它工作。 –