Как вызвать дочернюю функцию из родительского компонента с событием
У меня есть функция по событию click в родительском HTML.
<span (click)="onFilterClick()" class="filter-icon">
<mat-icon>keyboard_arrow_down</mat-icon></span>
<m-scp-filter-template [openFilter]="true" *ngIf="templateFor === 'col1' "></m-scp-filter-template>
дочерний компонент в родительском TS
@ViewChild(ScpFilterTemplateComponent) myChild;
функция у родителя тс
onFilterClick() {
this.myChild.openMenu();
}
и вызвал функцию у ребенка тс
openMenu() {
console.log('successfully executed.');
}
но я получаю ошибку
'TypeError: Невозможно прочитать свойство'openMenu'из неопределенного в ScpDataTableComponent.'
4 ответа
- Как
@ViewChild
ссылается на существующее дочернее представление / селектор, ваше дочернее представление должно существовать в родительском HTML. Если твой*ngIf
возвращает false, Angular даже не создает дочернее представление в родительском HTML. Так что вашиmyChild
само по себе в этом случае будет неопределенным, и вы не сможете получить доступ к каким-либо методам / свойствам дальше.- Существует также альтернативный обход - вы можете создать экземпляр своего дочернего класса и вызвать метод, но это не рекомендуется.
Вот минимальное воспроизведение обоих сценариев.
попробуйте сделать этот дочерний метод общедоступным...
public openMenu() {
console.log('successfully executed.');
}
Вы можете попробовать с сеттером?
@ViewChild(ScpFilterTemplateComponent)
set _myChild(v) {
setTimeout(() => { this.myChild= v; }, 0);
}
или завернуть this.myChild.openMenu();
в течение тайм-аута и т. д.
Вот копия из документации Angular https://angular.io/guide/component-interaction
import { AfterViewInit, ViewChild } from '@angular/core';
import { Component } from '@angular/core';
import { CountdownTimerComponent } from './countdown-timer.component';
@Component({
selector: 'app-countdown-parent-vc',
template: `
<h3>Countdown to Liftoff (via ViewChild)</h3>
<button (click)="start()">Start</button>
<button (click)="stop()">Stop</button>
<div class="seconds">{{ seconds() }}</div>
<app-countdown-timer></app-countdown-timer>
`,
styleUrls: ['../assets/demo.css']
})
export class CountdownViewChildParentComponent implements AfterViewInit {
@ViewChild(CountdownTimerComponent)
private timerComponent: CountdownTimerComponent;
seconds() { return 0; }
ngAfterViewInit() {
// Redefine `seconds()` to get from the `CountdownTimerComponent.seconds` ...
// but wait a tick first to avoid one-time devMode
// unidirectional-data-flow-violation error
setTimeout(() => this.seconds = () => this.timerComponent.seconds, 0);
}
start() { this.timerComponent.start(); }
stop() { this.timerComponent.stop(); }
}
В примере start()
а также stop()
вызов метода соответствующих методов дочернего компонента при нажатии кнопок родительского компонента
Если для дочернего компонента установлен *ngIf, вы можете исправить это с помощью Angular 2 @ViewChild в *ngIf