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

#angular #parent #emit

Вопрос:

У меня есть одна проблема. Я пытаюсь динамически повторить компонент ngFor , и мой основной компонент хочет, чтобы все данные ребенка повторялись с помощью нажатия кнопки.

Посмотрите ниже для более глубокого понимания :

введите описание изображения здесь

Я хочу получить все внутренние данные дочернего компонента в родительский компонент по нажатию кнопки родительского компонента. Но я не знаю, как прослушать событие щелчка родительской кнопки в дочернем компоненте.

Не могли бы вы, пожалуйста, помочь мне реализовать такой сценарий. Я буду очень благодарен, если кто-нибудь мне поможет.

Примечание : Я не могу использовать какую-либо ссылку через viewchild дочернего компонента для вызова дочернего метода от родителя, потому что дочерние компоненты отображаются динамически через *ngFor

Комментарии:

1. child component's internal data что это значит ? Вы хотите передать событие щелчка дочернему компоненту или наоборот? Отображаются ли дочерние компоненты к моменту нажатия на кнопки? Добавьте еще немного контекста и кода.

2. Да, я хочу, чтобы все данные дочернего компонента попадали в родительский компонент при нажатии на родительскую кнопку. Дочерние компоненты динамически добавляются другой кнопкой, которая не упоминается в изображении.

3. Я уже использую его для выделения данных из дочернего компонента. но проблема в том, что при нажатии на кнопку родителя я хочу выдавать данные. как я могу обнаружить событие щелчка родителя в дочернем ?

4. О каких (детских) данных мы здесь говорим? Услуга может иметь смысл..?

5. дочерний компонент будет обрабатывать один вид json, например данные: { ключ: значение, ключ: значение } каждый дочерний компонент будет выдавать один объект json

Ответ №1:

Я не совсем понимаю, что вы имеете в виду child component's internal data . Предполагая, что вы хотите вызвать методы и получить доступ к свойствам. Вы можете использовать @ViewChild

 import { Component } from '@angular/core';
@Component({ 
  selector: 'child-cmp', 
  template: `<h2> Child Component</h2> ` 
})
export class ChildComponent {

  TestCmp() { 
   console.log("Child component!"); 
  }
 }
 

В родительском компоненте вы можете сделать это:

   import { Component, OnInit, ViewChild } from '@angular/core';
    import { ChildComponent } from '../child/child'; 
    @Component({ 
               selector: 'parent-app', 
               template: `<child-cmp></child-cmp>` 
              }) 
    export class parentComponent implements OnInit{ 
        @ViewChild(ChildComponent, {static: false }) child: ChildComponent ; 

// it will be available after ngAfterViewInit

        ngAfterViewInit() { 
           this.child.ChildTestCmp(); } 
}
 

Описанный выше метод может помочь вам вызвать различные методы и получить доступ к свойствам.

Теперь, если вы хотите передать событие дочернему компоненту, вы можете использовать RXJS Subject . Всякий раз, когда в родительском компоненте происходит событие, вы можете получить значение в дочернем компоненте.

Для этого вам следует создать службу и инициализировать ее. test.service.ts

 import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';


@Injectable({
  providedIn: 'root'
})
export class TestService { 
   constructor () {}
   const subject = new Subject<number>();
}
 

Импортируйте службу в Дочерний и Родительский компоненты:

 import { Component, OnInit, ViewChild } from '@angular/core';
import { TestService } from 'test.service'
    import { ChildComponent } from '../child/child'; 
    @Component({ 
               selector: 'parent-app', 
               template: `<child-cmp></child-cmp>` 
              }) 
    export class parentComponent implements OnInit{ 
        @ViewChild(ChildComponent, {static: false }) child: ChildComponent ; 

       constructor(private testService: TestService) {}
// it will be available after ngAfterViewInit

        ngAfterViewInit() { 
           this.child.ChildTestCmp(); } 
    
         someEventHappen() {
           this.testService.subject(true);
         }

}
 

В дочернем компоненте вы можете получить событие:

 import { Component , OnDestroy} from '@angular/core';
import { TestService } from 'test.service'
@Component({ 
  selector: 'child-cmp', 
  template: `<h2> Child Component</h2> ` 
})
export class ChildComponent implements OnDestroy{
  subs: subscription[] = [];
 constructor(private testService: TestService) {
    // unsubscribe all the subs
     const subs = this.testService.subject().subscribe(data => {
      // do something
      });
    this.subs.push(subs);

}

  TestCmp() { 
   console.log("Child component!"); 
  }

   ngOnDestroy() {
    this.subs.forEach(sub => sub.unsubscribe());
   }
 }

 

Вы также можете использовать одну и ту же службу для хранения данных для всех детей, хотя я бы посоветовал вам создать для них управление состоянием, и это поможет вам поддерживать его в хорошем состоянии.