Tengo un escenario simple, ¡pero simplemente no puedo hacerlo funcionar!
En mi opinión, muestro algo de texto en un cuadro con altura limitada.
El texto se obtiene del servidor, por lo que la vista se actualiza cuando llega el texto.
Ahora tengo un botón 'expandir' que tiene un ngIf que debería mostrar el botón si el texto en el cuadro se desborda.
El problema es que debido a que el texto cambia cuando se recupera, la condición del botón 'expandir' se vuelve true después de que finaliza la detección de cambios de Angular...
Entonces recibo este error: La expresión ha cambiado después de que se verificó. Valor anterior: 'falso'. Valor actual: 'verdadero'.
Obviamente el boton no aparece...
vea este Plunker (verifique la consola para ver el error...)
¿Alguna idea de cómo hacer que esto funcione?
este error ocurre porque estás en dev mode de desarrollo:
En dev mode de desarrollo, la detección de cambios agrega un giro adicional después de cada ejecución regular de detección de cambios para verificar si el modelo ha cambiado.
entonces, para forzar la detección de cambios, ejecute el siguiente tick, podríamos hacer algo como esto:
export class App implements AfterViewChecked { show = false; // add one more property constructor(private cdRef : ChangeDetectorRef) { // add ChangeDetectorRef //... } //... ngAfterViewChecked() { let show = this.isShowExpand(); if (show != this.show) { // check if it change, tell CD update view this.show = show; this.cdRef.detectChanges(); } } isShowExpand() { //... } }Demostración en vivo: https://plnkr.co/edit/UDMNhnGt3Slg8g5yeSNO?p=preview
Hacer que el detector de cambios se ejecute después de que ngAfterContentChecked resolvió el problema por mí
ejemplo de la siguiente manera:
import { ChangeDetectorRef,AfterContentChecked} from '@angular/core' export class example implements OnInit, AfterContentChecked { ngAfterContentChecked() : void { this.changeDetector.detectChanges(); } }Aunque, a medida que leo algunos de los artículos, este problema se resuelve en el modo de producción sin ninguna solución requerida.
A continuación se muestra la posible razón de tal problema:
Hace cumplir un flujo de datos unidireccional: cuando los datos en nuestras clases de controlador se actualizan, la detección de cambios se ejecuta y actualiza la vista.
Pero esa actualización de la vista no desencadena cambios adicionales que, a su vez, desencadenan actualizaciones adicionales de la vista.
https://blog.angular-university.io/how-does-angular-2-change-detection-really-work/
Por alguna razón, la respuesta de @ Tiep Phan no me funcionó para forzar la detección de cambios, pero sí lo hizo el uso de setTimeout (que también fuerza la detección de cambios).
También solo tuve que agregarlo a la línea ofensiva, y funcionó bien con el código que ya tenía en ngOnInit en lugar de tener que agregar ngAfterViewInit.
Ejemplo:
ngOnInit() { setTimeout(() => this.loadingService.loading = true); asyncFunctionCall().then(res => { this.loadingService.loading = false; }) }Más detalles aquí: https://github.com/angular/angular/issues/6005