Как вызвать дочернюю функцию из родительского компонента с событием

У меня есть функция по событию 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

Другие вопросы по тегам