angular - formularios - ExpressionChangedAfterItHasBeenCheckedError: La expresión ha cambiado después de que se verificó. Valor anterior: ''indefinido''
ng src angular 4 (2)
El gancho del ciclo de vida de ngAfterContentChecked
se activa cuando ya se han finalizado las actualizaciones de enlaces para los componentes / directivas secundarios. Pero está actualizando la propiedad que se usa como entrada de enlace para la directiva ngClass
. Ese es el problema. Cuando Angular ejecuta la etapa de validación, detecta que hay una actualización pendiente de las propiedades y arroja el error.
Para entender mejor el error, lea estos dos artículos:
- Todo lo que necesita saber sobre el error
ExpressionChangedAfterItHasBeenCheckedError
- Todo lo que necesitas saber sobre detección de cambios en Angular.
Piense por qué necesita cambiar la propiedad en el gancho del ciclo de vida de ngAfterViewInit
. Cualquier otro ciclo de vida que se desencadene antes de que ngAfterViewInit/Checked
funcione, por ejemplo, ngOnInit
o ngDoCheck
o ngAfterContentChecked
.
Así que para solucionarlo, mueva renderWidgetInsideWidgetContainer
al gancho del ciclo de vida ngOnInit()
.
Sé que hay muchas de las mismas preguntas publicadas en stackoverflow e intenté diferentes soluciones para evitar el error de tiempo de ejecución, pero ninguna de ellas me funciona.
Código componente y HTML
export class TestComponent implements OnInit, AfterContentChecked {
@Input() DataContext: any;
@Input() Position: any;
sampleViewModel: ISampleViewModel = { DataContext: : null, Position: null };
constructor(private validationService: IValidationService, private modalService: NgbModal, private cdRef: ChangeDetectorRef) {
}
ngOnInit() {
}
ngAfterContentChecked() {
debugger;
this.sampleViewModel.DataContext = this.DataContext;
this.sampleViewModel.Position = this.Position;
}
<div class="container-fluid sample-wrapper text-center" [ngClass]="sampleViewModel.DataContext?.Style?.CustomCssClass +'' samplewidget-''+ sampleViewModel.Position?.Columns + ''x'' + sampleViewModel.Position?.Rows">
//some other html here
</div>
Tenga en cuenta: este componente se carga dinámicamente usando DynamicComponentLoader
Después de mi resolución de problemas he identificado un par de problemas
En primer lugar, este componente hijo se carga dinámicamente utilizando DynamicComponentResolver y pasando los valores de entrada como se muestra a continuación
ngAfterViewInit() {
this.renderWidgetInsideWidgetContainer();
}
renderWidgetInsideWidgetContainer() {
let component = this.storeFactory.getWidgetComponent(this.dataSource.ComponentName);
let componentFactory = this._componentFactoryResolver.resolveComponentFactory(component);
let viewContainerRef = this.widgetHost.viewContainerRef;
viewContainerRef.clear();
let componentRef = viewContainerRef.createComponent(componentFactory);
debugger;
(<IDataBind>componentRef.instance).WidgetDataContext = this.dataSource.DataContext;
(<IDataBind>componentRef.instance).WidgetPosition = this.dataSource.Position;
}
Incluso si cambié el componente html de mi hijo, como se muestra a continuación, obtengo este mismo error. Solo agregue un atributo angular ngclass
<div class="container-fluid ds-iconwidget-wrapper text-center" [ngClass]="Sample">
</div>
Mi enlace de datos y todo funcionan bien. ¿Debo hacer algo en el componente principal? Ya probé todos los eventos del ciclo de vida en el componente hijo
Tiene que decirle a angular
que actualizó el contenido después de ngAfterContentChecked
, puede importar ChangeDetectorRef
desde @angular/core
y call detectChanges
import {ChangeDetectorRef } from ''@angular/core'';
constructor( private cdref: ChangeDetectorRef ) {}
ngAfterContentChecked() {
this.sampleViewModel.DataContext = this.DataContext;
this.sampleViewModel.Position = this.Position;
this.cdref.detectChanges();
}