Angular: вызов функции родительского компонента, когда все дочерние компоненты завершают загрузку данных - PullRequest
0 голосов
/ 03 апреля 2020

Я использую Angular6 и застрял в ситуации, когда у меня есть родительский компонент (скажем, родительский), который имеет 3 дочерних компонента (скажем, child1, child2, child3). parent-component. html выглядит следующим образом:

<div>
  <child1></child1>
  <child2></child2>
  <child3></child3>
</div>

Все дочерние компоненты вызывают свои службы (которые, в свою очередь, извлекают данные из http API) и загружают свои собственные данные. Все компоненты имеют разное время загрузки данных (скажем, у child1 есть 1 se c, у child2 есть 2 se c и у child3 есть 3 se c).

Я хочу выполнить функцию в paren, когда ВСЕ три дочерних компонента загрузили свои данные, полученные от службы.

Ответы [ 2 ]

0 голосов
/ 03 апреля 2020

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

Вы можете создать несколько тем, которые будут передаваться в один основной предмет, которым родительский компонент может питаться, используя функцию zip, чтобы узнать, фоновые звонки окончены. Попробуйте следующее

Общая служба

import { zip } from 'rxjs';

@Injectable()
export class ApiService {
  private apiOneStatusSource = new Subject<boolean>();
  private apiTwoStatusSource = new Subject<boolean>();
  private apiThreeStatusSource = new Subject<boolean>();

  private apisStatusSource = new Subject<boolean>();

  private apiOneStatus$ = this.apiOneStatusSource.asObservable();
  private apiTwoStatus$ = this.apiOneStatusSource.asObservable();
  private apiThreeStatus$ = this.apiOneStatusSource.asObservable();

  private apisStatus$ = this.apisStatusSource.asObservable();

  constructor() {
    zip(this.apiOneStatus$, this.apiTwoStatus$, this.apiThreeStatus$).subscribe(    // <-- use `zip` to check if all the observables have been emitted
      statuses => {
        if (statuses.every(status => status === true)) {
          this.apisStatusSource.next(true);
        }
      }
    );
  }

  public setApiOneStatus(status: boolean) {
    this.apiOneStatusSource.next(status);
  }

  public setApiTwoStatus(status: boolean) {
    this.apiTwoStatusSource.next(status);
  }

  public setApiThreeStatus(status: boolean) {
    this.apiThreeStatusSource.next(status);
  }

  public getApisStatus() {
    return this.apisStatus$;
  }
}

Родительский компонент

ngOnInit() {
  this.apiService.getApisStatus.subscribe(
    status => {
      // api from all 3 child compnents have returned values - proceed further
    }
  );
}

Дочерние компоненты

this.apiService.componentApiCall().subscribe(
  response => {
    // handle response
    this.apiService.setApiOneStatus(true);    // <-- set corresponding status here: setApiTwoStatus for child 2 and so on...
  },
  error => {
    // handle error
    this.apiService.setApiOneStatus(false);   // <-- set corresponding status here: setApiTwoStatus for child 2 and so on...
);
0 голосов
/ 03 апреля 2020

Вы можете добавить метод вывода к дочерним компонентам для генерации при загрузке данных, что-то вроде этого:

child.ts

import { Component, Output, EventEmitter } from '@angular/core';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-childx',
  templateUrl: './childx.component.html',
  styleUrls: ['./childx.component.scss']
})
export class Childx {
  data: Data;
  // output
  @Output() dataLoaded = new EventEmitter<string>();

  constructor() { }

  ngOnInit() {
    // emit after loading data
  }

  emit() {
    this.dataLoaded.emit('Childx');
  }

}

parent. html

<div>
  <child1 (dataLoaded)="dataLoaded($event)"></child1>
  <child2 (dataLoaded)="dataLoaded($event)"></child2>
  <child3 (dataLoaded)="dataLoaded($event)"></child3>
</div>

parent.ts

childrenDataLoadedCount = 0;
dataLoaded(child: string) {
  childrenDataLoadedCount++;
  if (childrenDataLoadedCount === 3) {
    // here all children load data
  }
}

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

...