Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

1.3K
Vistas
Angular: Wait until all child components have rendered before running code

I have a directive that's at the top level of the app and queries elements via document.querySelector and hands them to fromEvent. The problem is, that when the code in the directive's ngAfterViewInit runs, the DOM isn't fully rendered yet so the element query returns null.

I could run the code in setTimeout with some arbitrary amount of time, but that doesn't seem like a sustainable, and flexible solution.

Any ideas for how this can be elegantly handled?

Right now, my code looks like some variation of this:

ngAfterViewInit() {
  const trackedEl = document.querySelector('#myInput');
  const input$ = fromEvent(trackedEl, 'input')
    .pipe(
      map((inputEvent: any) => inputEvent.target.value)
    )
    .subscribe((v) => {
      console.log(`Got to the observable:: ${v}`, count++);
    })
}
over 4 years ago · Santiago Trujillo
4 Respuestas
Responde la pregunta

0

I think your best approach here would be to use something like a ViewChild.

So assuming your querySelector targets an <input> tag your html would be like (note the #myInput decorator):

<input #myInput ....>

Your .ts file would be:

 @ViewChild('myInput', { static: true })
  input?: ElementRef<HTMLElement>;

Then because we only want to resolve the event when it is subscribed to:

const input$ = defer(() => fromEvent(this.input, 'input').pipe(
      map((inputEvent: any) => inputEvent.target.value)
    )
    .subscribe((v) => {
      console.log(`Got to the observable:: ${v}`, count++);
    });

Something to this affect, but certainly ViewChild being key here.

over 4 years ago · Santiago Trujillo Denunciar

0

ngAfterViewInit lifecycle hook that angular calls after it creates all the component's child views. So you have to implement it on the root AppComponent. Then keep an observable into a service or state and just subscribe to it anywhere you wanna check.

root AppComponent:

export class AppComponent implements AfterViewInit {
  title = "Angular App";
  constructor(private data: DataService){}
  ngAfterViewInit() {
    this.data.rendered.next(true);
  }
}

subscribing it anywhere:

export class HighlightDirective {
  constructor(private data: DataService) {
    this.data.rendered.subscribe(rendered => {
     // all components rendered here, write you code
    });
  }
}
over 4 years ago · Santiago Trujillo Denunciar

0

I think this could be an approach:

ngAfterViewInit() {
  defer(() => fromEvent(document.querySelector('#myInput'), 'input'))
    .pipe(
      subscribeOn(asyncScheduler),
      map((inputEvent: any) => inputEvent.target.value)
    )
    .subscribe((v) => {
      console.log(`Got to the observable:: ${v}`, count++);
    })
}

This approach is still resorting something like setTimeout, but in a more elegant way. This is achieved by using defer + subscribeOn.

By providing asyncScheduler to subscribeOn, we obtain a setTimeout-like functionality. The defer operator has been used because we want to evaluate that function which queries the DOM when source is subscribed, and recall that the subscription time is delayed by the subscribeOn operator.
So, by the time the source is subscribed, the DOM should be ready to be queried.

I know this is just a workaround for setTimeout, but I thought it would look more fancy with some interesting RxJS operators.

over 4 years ago · Santiago Trujillo Denunciar

0

I ended up finding the solution I was looking for.

The child elements were not rendered in time likely because they were responding to some outstanding http event that hadn't yet returned a response. After reading through the documentation for change detection and ngZone, it looked like outstanding http events count as "micro tasks."

The below code is what worked for me.

ngOnInit() {
    this.ngZone.onMicrotaskEmpty.pipe(take(1)).subscribe((a) => {
      this.initiateElementEventListeners();
    });
}
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda