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

268
Visualizações
Why is Angular calling `registerOnChange` after `ngOnDestroy` on custom ControlValueAccessor component?

After creating a custom form element, I noticed that when I navigated away from a route that hosted that custom form element, Angular would call the form element's ngOnDestroy method and then it would call the form element's registerOnChange and registerOnTouched methods. I'm not sure why it would call these two methods at this point, but I definitely don't understand why it would call them after ngOnDestroy.

I've created a minimal reproduction of this bug here: https://stackblitz.com/edit/angular-ivy-6jhgh6

This behavior is problematic for me because in my actual application, I'm destroying an instance of a CodeMirror editor and setting the variable reference to null, but in the registerOnTouched method, I reference that variable. This results in a null reference error. This just started happening after upgrading to Angular 12.

over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

Calling registerOnChange and registerOnTouched methods after the component's ngOnDestroy hook has been invoked is a consequence of calling FormControlName.ngOnDestroy().

When a view is destroyed, my understanding from this function is that all of the onDestroy hooks from the destroyed view will be invoked. So, that's why the form directives of that view will have their onDestroy hook called too.

This is what happens on FormControlName.ngOnDestroy():

// `formDirective` refers to the parent `FormGroup` directive
this.formDirective.removeControl(this);

This is what happens on FormGroupDirective.removeControl(): :

removeControl(dir: FormControlName): void {
  cleanUpControl(dir.control || null, dir, /* validateControlPresenceOnChange */ false);
  removeListItem(this.directives, dir);
}

And finally, cleanUpControl is where the registerOnChange and registerOnTouched methods are invoked from:

// Reverts configuration performed by the `setUpControl` control function.
// Effectively disconnects form control with a given form directive.
// This function is typically invoked when corresponding form directive is being destroyed.
export function cleanUpControl(/* ... */) {
  /* ... */
  const noop = () => {
    if (validateControlPresenceOnChange && (typeof ngDevMode === 'undefined' || ngDevMode)) {
      _noControlError(dir);
    }
  };

  if (dir.valueAccessor) {
    dir.valueAccessor.registerOnChange(noop);
    dir.valueAccessor.registerOnTouched(noop);
  }
  /* .... */
}

So, based on my understanding, it is part of the cleanup mechanism. It is indeed a bit inconvenient because those methods are called when the view is set up and also when the view is destroyed. I guess the solution is to first check for null/undefined values.

If you want to explore further, you can just use the debugger keyword:

registerOnChange(fn: any): void {
  debugger;
  this.con.log(`registerOnChange (${this.id})`);
}

and then open the DevTools in the StackBlitz project.

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