Estoy mostrando y ocultando un FormControl basado en otro FormControl en el mismo FormGroup, que funciona usando el método a continuación, pero cuando trato de restablecer la entrada oculta, así que al enviar su valor no se envía, aparece el siguiente error.
Método de componente
public hasOtherFundingSource(index: number) { const formGroup = this.overviewFunds.at(index); const source = formGroup.get('source').value; if (source !== 'other') { formGroup.get('other_source_desc').reset(); // Throws error return false; } else { return true; } }Error
ExampleComponent.html:12 ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'true'. Current value: 'false'. Con la ayuda de @yurzui, creé un plunker que muestra el error. Simplemente cambie other a another en el campo de selección y observe cómo la consola cierra la sesión del error. El error parece estar relacionado con dividir FormGroup en subcomponentes para reducir el tamaño y la lógica en cada clase.
Si observa el primer plunker que se creó, el error no ocurre cuando el formulario se encapsula en el componente de la aplicación.
Debe evitar cualquier efecto secundario dentro de las funciones que se ejecutarán en cada verificación de vista
<div *ngIf="hasOtherFundingSource(i)"> La función hasOtherFundingSource se ejecutará dos veces en modo dev en cada marca de la aplicación.
Hay una directiva NgControlStatus que verifica el estado de validación.
En la primera verificación, su formulario es válido
Después de eso, está llamando a formGroup.get('other_source_desc').reset(); y el estado deja de ser invalid
Entonces angular está ejecutando view.checkNoChanges() y obtienes ExpressionChangedAfterItHasBeenCheckedError
Entonces, de acuerdo con https://angular.io/docs/ts/latest/guide/template-syntax.html#!#no-visible-side-effects
Una expresión de plantilla no debe cambiar ningún estado de la aplicación que no sea el valor de la propiedad de destino.
Esta regla es esencial para la política de "flujo de datos unidireccional" de Angular. Nunca debe preocuparse de que leer el valor de un componente pueda cambiar algún otro valor mostrado. La vista debe ser estable a lo largo de una sola pasada de renderizado.
Para solucionar tu problema hice lo siguiente:
1) Se agregó el evento ngModelChange para select el control
<select formControlName="source" (ngModelChange)="sourceChanged($event, i)"> 2) Mover el efecto secundario de hasOtherFundingSource a la función sourceChanged
sourceChanged(value: string, index: number) { if (value !== 'other') { const formGroup = this.overviewFunds.at(index); formGroup.get('other_source_desc').reset(); } }