Как вызвать дочернюю функцию из родительского компонента с событием - PullRequest
0 голосов
/ 29 января 2019

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

функция в родительском ts

onFilterClick() {
  this.myChild.openMenu();
}

и вызвал функцию у дочернего ts

openMenu() {
     console.log('successfully executed.');
}

, но я получаю ошибку

'TypeError: Невозможно прочитать свойство' openMenu 'undefined в ScpDataTableComponent.'

Ответы [ 3 ]

0 голосов
/ 29 января 2019

Можете ли вы попробовать с сеттером?

@ViewChild(ScpFilterTemplateComponent) 
set _myChild(v) {
  setTimeout(() => { this.myChild= v; }, 0);
}

или обернуть this.myChild.openMenu(); в тайм-аут и т. Д.

0 голосов
/ 29 января 2019
  • Поскольку @ViewChild относится к существующему дочернему представлению / селектору, ваше родительское представление должно существовать в родительском HTML .Если ваш *ngIf вернет false , Angular даже не создаст дочернее представление в родительском HTML.Таким образом, ваш myChild сам будет неопределенным в этом случае, и вы не сможете получить доступ к каким-либо методам / свойствам в дальнейшем.
  • Существует также альтернативный обход - вы можете создать экземпляр вашего дочернего класса и вызвать метод, но не рекомендуется .

Здесь - минимальное воспроизведение обоих сценариев.

0 голосов
/ 29 января 2019

Вот копия из документации Angular https://angular.io/guide/component-interaction#parent-calls-an-viewchild

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 in * ngIf

...