我尝试了一个非常简单的示例,通过 @ViewChild()装饰器从父组件调用子组件中的 childMethod 。遗憾的是,ViewChild变量始终未定义。
子组件
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
任何澄清都会有所帮助。
答案 0 :(得分:5)
这是罪魁祸首:
<form>
<input value="Dave" name="Name"><br>
<input value="dave124" name="Username">
</form>
*ngIf="selectedCharacter"
会阻止ngIf
在太晚之前被实例化。您可以将其移至ViewChild
的模板内,以便在父组件中获得MyCharacter
引用,而不会更改应用的任何行为。