Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

1.3K
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda