kk-at-cbx
kk-at-cbx

Reputation: 329

how to know if child components are loaded in Angular

I have a parent component which contains a bunch of child components. I would like to do some action after all components are loaded.

How to make a call back when all child components are loaded in Angular?

Thanks

PS. I would like a similar function like "ionViewDidEnter" of Ionic in pure Angular.

Upvotes: 4

Views: 4559

Answers (1)

Owen Kelvin
Owen Kelvin

Reputation: 15083

I would approach the problem like below:

Declare a service

export class ChildComponentsLoadedService () {
  component1LoadedSubject$ = new BehaviourSubject(false)
  component2LoadedSubject$ = new BehaviourSubject(false)
  component3LoadedSubject$ = new BehaviourSubject(false)
  ...
  allComponentsLoaded$ = combineLatest([
    component1LoadedSubject$.asObservable(),
    component1LoadedSubject$.asObservable(),
    component1LoadedSubject$.asObservable(),
    ...
  ]).pipe(
    map(componentsLoaded => componentsLoaded.every(loaded => loaded)),
    filter(loaded => loaded === true)
   )
}

Parent Component


constructor(private childComponentsLoadedService: ChildComponentsLoadedService) { }

childComponentsLoaded$ = this.childComponentsLoadedService.allComponentsLoaded$;

ngOnInit() {
  this.childComponentsLoaded$.subscribe({
    next: () => {
      // Now all components have loaded here
    }
  })
}

In the child i component

constructor(private childComponentsLoadedService: ChildComponentsLoadedService) { }
ngOnInit() {
  this.componentiLoadedSubject$.next(true)
}

Dynamic Components

Declare a service

export class ChildComponentsLoadedService () {
  componentLoadedSubject$ = new BehaviourSubject([false]);
  componentLoadedAction$ = this.componentLoadedSubject$.asObservable()
  allComponentsLoaded$ = this.componentLoadedAction$.pipe(
    filter(component=> component.every(loaded => loaded))
  )
  markComponentAsLoaded(index: number) {
    let currentLoadStatus = [...this.componentLoadedSubject$.value];
    currentLoadStatus[index] = true
    this.componentLoadedSubject$.next([...currentLoadStatus])
  }
}

Parent Component

constructor(private childComponentsLoadedService: ChildComponentsLoadedService) { }
noOfChildComponents = 14;
ngOnInit() {
  
this.componentiLoadedSubject$.next(Array(this.noOfChildComponents).fill(false));
this.childComponentsLoaded$.subscribe({
    next: () => {
      // Now all components have loaded here
    }
  })
}

Child Component

@Input() componentIndex;
constructor(private childComponentsLoadedService: ChildComponentsLoadedService) {}
ngOnInit() {
  
  this.markComponentAsLoaded(componentIndex)
}

The approach uses the service to communicate between the parent component and the child components

Upvotes: 1

Related Questions