Angular: EXCEPCIÓN: La expresión ha cambiado después de que se verificó.

Creado en 18 dic. 2015  ·  147Comentarios  ·  Fuente: angular/angular

Comentario más útil

Esto no es un error, es una característica del modo de desarrollo que funciona según lo previsto. Llamar a enableProdMode( ) : vea el plunk actualizado al iniciar la aplicación para evitar que se lance la excepción.

Dicho esto, se lanza por una buena razón: en resumen, después de cada ronda de detección de cambios, el modo de desarrollo realiza inmediatamente una segunda ronda para verificar que no haya cambiado ningún enlace desde el final de la primera, ya que esto indicaría que se están produciendo cambios. mediante la propia detección de cambios.

En su plunk, tiene el enlace [attr.spinner]=isLoading , y isLoading cambia como resultado de su llamada a this.load() , que ocurre cuando se dispara ngAfterViewInit , que ocurre como parte del turno de detección de cambios inicial. Sin embargo, eso en sí mismo no es problemático: el problema es que this.load() cambia un enlace pero no activa una nueva ronda de detección de cambios, lo que significa que este enlace no se actualizará hasta alguna ronda futura de detección de cambios.

Todos 147 comentarios

Me he enfrentado a un problema similar y parece deberse a cómo se inicializa un niño y cómo un padre puede actualizar al niño como parte de su proceso de inicialización. Tengo una muestra similar con una solución fea usando zone: http://plnkr.co/edit/GI45u805pnFUtFeORnxn?p=preview , con la solución similar a la siguiente:

constructor (zona privada: NgZone) {}

ngAfterViewInit (): void {
this._zone.overrideOnTurnDone (() => {
this.child.title = 'título del padre';
});
}

Esto no es un error, es una característica del modo de desarrollo que funciona según lo previsto. Llamar a enableProdMode( ) : vea el plunk actualizado al iniciar la aplicación para evitar que se lance la excepción.

Dicho esto, se lanza por una buena razón: en resumen, después de cada ronda de detección de cambios, el modo de desarrollo realiza inmediatamente una segunda ronda para verificar que no haya cambiado ningún enlace desde el final de la primera, ya que esto indicaría que se están produciendo cambios. mediante la propia detección de cambios.

En su plunk, tiene el enlace [attr.spinner]=isLoading , y isLoading cambia como resultado de su llamada a this.load() , que ocurre cuando se dispara ngAfterViewInit , que ocurre como parte del turno de detección de cambios inicial. Sin embargo, eso en sí mismo no es problemático: el problema es que this.load() cambia un enlace pero no activa una nueva ronda de detección de cambios, lo que significa que este enlace no se actualizará hasta alguna ronda futura de detección de cambios.

Necesito configurar mi componente en afterViewInit porque tengo ChildView que se inicializa aquí. ¿Cuál es la forma correcta de realizar ese cambio en isLoading ? ¿Envuelve la llamada a this.load por setTimeout ?

Solo necesita hacer algo, cualquier cosa, que desencadene otra ronda de detección de cambios durante ese método: emitir un evento, lo que sea. Envolverlo en un tiempo de espera (cola de retroceso en ng1 :-P) es una forma en que funcionaría, pero me parece muy complicado en ng2.

No parece fácil de usar. Pienso en ese método como en el lugar donde puedo completar la inicialización de mi componente cuando sus hijos están definidos y ahora resulta que tiene algunas reglas personalizadas. Creo que debería forzar internamente la nueva ronda de detección de cambios para que esté oculta dentro de ng2 para el usuario.

¿Podría publicar una muestra más representativa de lo que está tratando de lograr aquí? si es su ruleta de imágenes, será mejor que use una encuadernación estándar.

@ AerisG222 lo mismo para ti. ¿Hay alguna razón por la que no pueda usar un enlace simple para lograr esto? Por lo general, no se recomienda anular el comportamiento de la zona.

@robwormald Sí, en ese caso podría hacer el enlace de propiedad. El caso real que tengo también involucra otra propiedad que es un poco más complicada: una matriz de objetos personalizados, pero que también podría establecerse mediante el enlace de propiedad.

Supongo que si no existiera @ViewChild , no me importaría demasiado, ya que esta sería la única forma razonable de transmitir la información. Sin embargo, estaba muy emocionado de ver @ViewChild para poder trabajar con referencias de componentes en el código. Esto simplifica el marcado y permite un mayor control a través del código, lo que además es valioso con el mecanografiado ya que hay más soporte de herramientas (como intellisense y verificación del tiempo de compilación). También simplifica el componente contenedor, ya que no tiene que realizar un seguimiento de las variables miembro que están destinadas solo a usarse como estado para el hijo.

Otro punto menor es que cuando mira a través de una aplicación usando la sintaxis de enlace de propiedad, debe inspeccionar la plantilla para ver quién está consumiendo los datos en última instancia. Esto sería más obvio cuando se conecta a través de un código.

He limpiado el código para mostrar solo lo que importa para el ejemplo. La idea es mostrar la ruleta solo mientras se carga la imagen y luego quitar la ruleta y mostrar la imagen. La imagen se carga solo cuando el elemento está visible en la pantalla.

inflate.ts

import {Component, Input, Renderer, ElementRef, AfterViewInit, ViewChild} from 'angular2/core';

@Component({
  selector: '[inflate]',
  templateUrl: './inflate.html',
  styleUrls: ['./inflate.css']
})
export class Inflate implements AfterViewInit {
  @Input('inflate') url: string;
  @ViewChild('holder') holder: ElementRef;
  isLoaded = false;
  isLoading = false;

  constructor(private renderer: Renderer) {}

  ngAfterViewInit() {
    setTimeout(_=> this.inflate()); // BUGFIX: https://github.com/angular/angular/issues/6005#issuecomment-165911194
  }

  inflate() {
    let bounds = <ClientRect>this.holder.nativeElement.getBoundingClientRect();
    if(bounds.bottom > 0 && bounds.top < window.innerHeight) {
      this.isLoading = true;
      let img = new Image();
      img.src = this.url;
      img.onload = _=> {
        this.isLoaded = true;
        this.isLoading = false;
        this.renderer.setElementStyle(this.holder,
          'background-image', 'url("' + this.url + '")');
      };
    }
  }
}

inflate.html

<image-holder #holder></image-holder>
<spinner *ngIf="isLoading"></spinner>

Necesito mantener la imagen no en el host porque, si bien se desvanece con la animación en la carga completa, no debería afectar la opacidad del fondo del host.

Tengo un problema potencialmente relacionado con una directiva anidada.
http://plnkr.co/edit/myX2Alx9jie2q0FDIME7?p=preview
Aquí estoy vinculando a ngStyle en progressBar.ts.
Estoy registrando el objeto de estilos antes de regresar para demostrar que son iguales.
También obtengo la ExpressionChangedAfterItHasBeenCheckedException.

@ svi3c , en realidad está devolviendo un objeto _diferente_. Cada llamada a función devolverá una nueva instancia de objeto que es "igual" a la anterior en términos de claves / valores, pero no en términos de instancias / referencias.

Hay varias formas de lidiar con esta situación:

  • actualizar valores en una instancia de objeto, en lugar de devolver una nueva copia
  • usando la estrategia ChangeDetectionStrategy.OnPush para que su función solo se invoque cuando cambie una de las entradas, por ejemplo: http://plnkr.co/edit/NWyVoTtkiAzqWJphLMbi?p=preview

Es posible que desee consultar https://github.com/ng-bootstrap/core/blob/master/src/progressbar/progressbar.ts como otro ejemplo de una directiva de barra de progreso para ng2 (usando HTML / CSS de bootstrap)

@ pkozlowski-opensource ¡Muchas gracias!
Solo leí https://angular.io/docs/ts/latest/guide/template-syntax.html#!#ngstyle y todavía no encontré estrategias de detección de cambios. ¡Eso es genial! :)

@drew-moore:

Solo necesita hacer algo, cualquier cosa, que desencadene otra ronda de detección de cambios durante ese método: emitir un evento, lo que sea.

¿Puede recomendarnos cuál es la forma _correct_ y _simplest_ para reactivar la detección de cambios dentro de ngAfterViewInit, asumiendo que todo lo que se necesita es una propiedad para actualizarse? ApplicationRef.tick() no funciona aquí ya que eso provoca la excepción 'ApplicationRef.tick se llama recursivamente'; emitir un evento solo para activar una detección de cambio se siente mal (y no funcionó para mí), y también setTimeout .

Según los comentarios aquí, parece ser un requisito bastante común actualizar una propiedad vinculada en ngAfterViewInit (debido a una dependencia de un componente secundario), por lo que Angular 2 parece no tener una forma simple de hacer esto.

Si actualizar una propiedad vinculada en ngAfterViewInit es lo _wrong_ que se debe hacer, ¿cuál es la alternativa?

Aquí hay uno rápido:

Desafío:
Establezca la altura del elemento dom (a través de una fórmula determinada) en función de su ancho representado.

Expectativa:
Cuando se renderice el elemento, obtenga el ancho y, basándose en él, calcule su altura.

Realidad:
setTimeout?

  ngAfterViewInit() {
    window.setTimeout(() =>
      this.elementHeight = (this.nativeElement.offsetWidth * this.randomImage.dim.h) / this.randomImage.dim.w
    )
  }

@Birowsky Plunker?

@zoechi Aquí hay un ejemplo: http://plnkr.co/edit/MML5uHEFQdL0k0TA5HtY

Puede alternar setTimeout en app/app.component.ts#21 en el gancho del ciclo ngAfterViewInit vida

También me he encontrado con algo similar al intentar implementar el método writeValue( newValue ) de un ngModel valueAccessor . Cuando trato de aplicar el newValue al componente, me dice que el valor ha cambiado (de mala manera). Como todos ustedes han encontrado, envolverlo en un setTimeout () lo "arregla"; pero no en una buena manera.

Tengo otro ejemplo . Es un poco más simple en el sentido de que se configura un @HostBinding() y se informa mediante un QueryList .

Igual que mi número 5950.

Algunas recomendaciones aquí sobre cómo hacer esto limpiamente.
http://stackoverflow.com/questions/34827334/triggering-angular2-change-detection-manually

Sin embargo, todavía estoy envuelto en setTimeout porque no pude conseguir que ninguno de ellos hiciera lo que necesito. Parece que podría ChangeDetectorRef.detectChanges() al final de una devolución de llamada y activar el CD .... ¿Me estoy perdiendo de algo? Quizás ayude a alguno de ustedes.

Estoy usando las extensiones de fuente de medios HTML5 para crear un contexto de audio basado en un elemento de video, por lo que se requiere el uso de @ViewChild . Según el contexto de audio, estoy tratando de mostrar información, como el número de canales. Sin embargo, también me encontré con este problema. ¿Cuál es la forma correcta de evitar esto?

@ElsewhereGames Es difícil saberlo sin ver un código real. ¿Puedes crear un Plunker?

@zoechi No tengo un error real que informar, solo digo que no acceder al DOM directamente, aunque es deseable, no siempre es algo que se pueda evitar (en respuesta al comentario de @robwormald ). Para conocer la API actual, consulte los documentos en createMediaElementSource .

Publiqué en enero con un problema de _ngModel_. Ahora, estoy de vuelta con el problema _ViewChildren_. Sin embargo, a diferencia de algunos de estos otros ejemplos, en realidad no estoy tratando de hacer nada en mi demostración. Es decir, mis controladores tienen lógica cero: son todos metadatos y enlaces de vista. Como tal, no estoy seguro de dónde tengo margen de maniobra para estropear las cosas:

http://www.bennadel.com/blog/3040-i-have-a-fundamental-misunderstanding-of-change-detection-in-angular-2-beta-8.htm

Se encuentra con un problema similar pero podría reescribir el código para solucionarlo. Me reí mucho con la publicación de

https://github.com/angular/angular/issues/6618

Hasta ahora, siempre había una forma de solucionarlo, pero lo sugeriré aquí nuevamente, como mínimo, el mecanismo de detección de cambios podría usar más documentación. @bennadel Tu problema me recuerda a otro problema,

https://github.com/angular/angular/issues/5177

donde resolver esto, se sugirió que se agregara un enlace de ciclo de vida adicional OnBeforeBinding / OnBeforeRendering. Parece que esa solución también resolvería su problema.

@tandu simplemente reemplaza ngAfterViewInit por ngOnInit

@tandu , realmente no importa cuándo comenzará su ruleta (cargando niño, cargando imagen en niño; para el usuario, todo se está cargando), solo importa cuando necesita apagarlo. Puede apagarlo en "ngAfterViewInit", usando setTimeout (estoy de acuerdo en que es feo), pero será incorrecto - el componente secundario debería disparar un evento cuando se complete la carga de la imagen, al componente principal. La carga del componente secundario y la carga de la imagen son 2 eventos diferentes.

@ e-oz https://github.com/angular/angular/issues/6005#issuecomment -165951692 Accedo a los límites de los niños para detectar si debo comenzar a cargar la imagen.

@tandu y podría mover toda esta verificación al código del componente secundario (sería legítimo en ngAfterViewInit del componente secundario) y enviar el evento al padre, cuando cambiar isLoading.

@ e-oz Defino el componente como #holder en html: <image-holder #holder></image-holder> . Entonces no hay un archivo js para eso.

así que créelo, de lo contrario no es necesario usar ngAfterViewInit, si View
no tiene componentes reales como hijos, no se renderizará nada.

El domingo, 13 de marzo de 2016 a las 15:18, tandu [email protected] escribió:

@ e-oz https://github.com/e-oz Defino el componente como #holder en html:

titular>

. Entonces no hay un archivo js para eso.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/angular/angular/issues/6005#issuecomment -195963389.

También puedo usar element.getElementsByTagsName o métodos similares y no usar ChildComponent. Definitivamente existen soluciones alternativas. Estoy bien con setTimeout fix. El problema es que el nombre del método sugiere que se puede usar para definir alguna lógica que quiera que los componentes secundarios se inicialicen y se unan al componente, pero el método no dice que se ejecuta en el medio del ciclo de detección de cambios, por lo que tenemos un largo hilo de quejas de diferentes personas.

@tandu Estoy absolutamente de acuerdo contigo en esto, es una limitación muy molesta.

Por lo que vale, he cambiado mi solución original a la siguiente, que está empezando a parecer un enfoque razonable. Quizás valga la pena intentarlo para su situación:

    constructor(private _changeDetectionRef : ChangeDetectorRef) { }

    ngAfterViewInit() : void {
        // your code

        this._changeDetectionRef.detectChanges();
    }

Recibo la misma excepción cuando uso la validación de formulario (entrada requerida). ¿Relacionado con este problema?

Plunker: http://plnkr.co/edit/Fp6XT5mC6ZCB14Z1gvTi?p=preview

@eivindr echó un vistazo rápido y no había visto ngFormControl en una entrada antes, no puedo ver por qué o qué significaría, ya que debería ir en el elemento del formulario para vincularlo a un grupo de control y la entrada individual tendría un correspondiente ngControl. En cualquier caso en su plunker quitar

 [ngFormControl]="formModel.find('title')" 

y corrige tu error.

Me niego a eliminar este problema :) Ayer, pude demostrar que mi problema estaba relacionado específicamente con enlaces de host que dependen de las propiedades de entrada :

http://www.bennadel.com/blog/3056-host-bindings-are-breaking-the-ngmodel-bridge-in-angular-2-beta-11.htm

Tengo que creer que esto es un error en este punto porque el componente tiene dos cosas que dependen de la entrada: la plantilla de vista y los enlaces de host, y _sólo uno de ellos_ está causando la excepción de cambio. Si ambos causaron el problema, pensaría en otra cosa; pero, dado que solo uno de ellos está causando el problema, debe ser un error, ¿verdad?

@eivindr También tengo el mismo problema al comenzar con un formulario en blanco y luego establecer el valor de los controles del formulario mediante programación. ¿Encontraste una solución alternativa?

@MarkPerryBV No, sigo recibiendo "ha cambiado después de que se verificó" cuando se requiere. Lo mismo ocurre con el validador de patrones. Pero minLength, etc. funciona.

@ user414 Si

@MarkPerryBV Encontré una solución que me funciona (por ahora). Tuve que enableProdMode (). Estoy usando ngIf en las entradas, por lo que también tuve que hacer un ChangeDetectorRef.detectChanges () después de que se renderizó la entrada (si no, la entrada no era válida a pesar de tener contenido).

El uso de enableProdMode() realmente no soluciona nada, solo enmascara el síntoma al evitar que haga la doble verificación e informarle que probablemente algo está mal.

La solución de AerisG222 parece mejor que usar un setTimeout . ¿Es realmente el caso de que el comportamiento previsto es tener que activar manualmente la detección de cambios después de llamar a addControl() con un validador?

El mismo problema aquí después de llamar a addControl (). Creo que addControl () debería llamar a ChangeDetectionRef.detectChanges ().

@CaptainCodeman Lo sé, fue una solución temporal.

Esto ya no fallará en el modo de desarrollo cuando esté usando ng2 @ beta17 , [email protected] , zone. [email protected]. Todavía tengo que llamar a ChangeDetectionRef.detectChanges ()

@eivindr ¿puedes actualizar tu plnkr a la solución beta17?
Estoy perdiendo la cabeza por esto, me niego a someterme a enableProdMode() .

@ AerisG222 ¡ Tu enfoque funciona para mí!

¿ Usar el enfoque que changeDetectionRef.detectChanges() ?

Tengo el mismo problema al intentar hacer una validación dinámica de formularios y luego restablecer el formulario. aquí está mi plunk

Pasos para reproducir. Envíe el formulario con ¿Está marcado el empleado? Después de que el formulario se actualice, verifique Es empleado nuevamente.

Estoy usando changeDetectionRef.detectChanges () en la función de envío.

gracias por esto @ AerisG222 :)

No me gusta toda esa solución de setTimeout. Propongo lo siguiente:

http://plnkr.co/edit/9umnTGsdFWhbaOBeftuZ?p=preview

Usar ChangeDetectorRef.detectChanges no siempre es un buen enfoque. Ejemplo por qué:

El componente principal llama a la API pública de los componentes secundarios durante su ngAfterViewInit . Esta llamada cambia la vinculación del niño. Llamar a detectChanges de los padres también resolvería el problema, pero eso significa que los padres deben saber cuándo llamar a detectChanges después de qué llamada a la API del niño. Notará que llamar a detectChanges en el método del niño que cambia el enlace en este caso no funciona cuando desea usar ChangeDetectionStrategy.OnPush .

Encontré este error al agregar niños dinámicamente a través de ViewContainerRef.createComponent() y luego actualizar la instancia secundaria. Estoy usando RC2 (y trato de no usar cosas depreciadas).

Inicialmente, la cosa funcionó bien (primer renderizado), pero luego agregué un componente que emitiría nuevos datos. Este evento fue escuchado por el componente principal, que actualizó su matriz de datos, lo que provocó la detección de cambios y la población de nuevos componentes secundarios dinámicos. El evento se desencadenó mediante el envío de un formulario. Si presioné el botón de enviar, todo estaba bien. Si presiono enter para generar el envío, produciría el error.

Terminé agregando ChangeDetectorRef.detectChanges() inmediatamente después de la creación y actualización del componente dinámico. No es un gran problema, pero parece extraño que, aunque acabo de agregar un nuevo componente a la vista, el sistema no activa automáticamente la detección de cambios para el niño.

@ aerisg222 ¿Necesito llamar a this._changeDetectionRef.detectChanges () después de cada cambio de propiedad de los hijos desde el padre?

Bueno, acabo de encontrar este problema. Tengo dos componentes hermanos que utilizan el mismo objeto de datos. Se supone que ambos objetos pueden actualizar la fuente de datos. La otra fuente realmente ve el cambio en el objeto, pero activa la expresión que ha cambiado después de que se verificó. Valor anterior: 'verdadero'. Valor actual: 'falso'

Esto me sucedió después de actualizar de RC1 a RC4

Aquí igual. Comencé a recibir esto nuevamente después de actualizar de RC1 a RC4.

Tal vez el cambio que causó esto debería haberse comunicado como un cambio rotundo en el registro de cambios ... porque mis cosas están rotas ahora.

Tenemos que esperar a la final.
Dejé de usar componentes secundarios porque la actualización de propiedades externas apesta.
Pensé que las zonas estaban aquí para eso ...

Aquí igual. La carga de componentes dinámicos a través de ViewComponentRef parece comportarse de manera diferente en RC2 y RC4 como lo hizo en RC1

Aquí están mis dependencias de trabajo:
"dependencias": {
"@ angular / común": "2.0.0-rc.1",
"@ angular / compiler": "2.0.0-rc.1",
"@ angular / core": "2.0.0-rc.1",
"@ angular / http": "2.0.0-rc.1",
"@ angular / platform-browser": "2.0.0-rc.1",
"@ angular / platform-browser-dynamic": "2.0.0-rc.1",
"systemjs": "0.19.31",
"core-js": "^ 2.4.0",
"reflect-metadata": "^ 0.1.3",
"rxjs": "5.0.0-beta.6",
"zone.js": "^ 0.6.12"
},
"devDependencies": {
"mecanografiado": "^ 1.8.10",
"mecanografía": "^ 1.0.4",
"concurrentemente": "^ 2.2.0",
"lite-server": "^ 2.2.2"
}

Y aquí están las dependencias que están produciendo el mencionado error:
"dependencias": {
"@ angular / común": "2.0.0-rc.4",
"@ angular / compiler": "2.0.0-rc.4",
"@ angular / core": "2.0.0-rc.4",
"@ angular / http": "2.0.0-rc.4",
"@ angular / platform-browser": "2.0.0-rc.4",
"@ angular / platform-browser-dynamic": "2.0.0-rc.4",
"systemjs": "0.19.31",
"core-js": "^ 2.4.0",
"reflect-metadata": "^ 0.1.3",
"rxjs": "5.0.0-beta.6",
"zone.js": "^ 0.6.12"
},
"devDependencies": {
"mecanografiado": "^ 1.8.10",
"mecanografía": "^ 1.0.4",
"concurrentemente": "^ 2.2.0",
"lite-server": "^ 2.2.2"
}

¡RC2 tampoco funciona!

Solo una pregunta, pero ¿hay alguna forma de obtener más información sobre el error? Por ejemplo, sería bueno saber cuál es la "expresión" cuando el error dice "¡la expresión cambia de 'verdadero' a 'falso' !.

También tengo exactamente el mismo problema después de actualizar de RC1 a RC4. Y lo que descubrí es debido a la función ngOnInit en mi Componente. Si comento esta función, el mensaje de error desaparece y todo funciona bien. ¿Alguna idea?

Cerrando este tema ya que es antiguo y se han tomado acciones. Si aún tiene el problema, asegúrese de crear un nuevo problema y complete la plantilla de problema con todos los detalles requeridos . Gracias

pero la gente decía que todavía están experimentando este problema en el nuevo rc ...

El miércoles 13 de julio de 2016 a las 00:52, Victor Berchet [email protected]
escribió:

Cerrado # 6005 https://github.com/angular/angular/issues/6005.

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/angular/angular/issues/6005#event -720794445, o silenciar
la amenaza
https://github.com/notifications/unsubscribe/AAgIEFEVZmE0M53XxNpzAYg9hJT_E_viks5qVAyGgaJpZM4G4J_s
.

Sí, acabo de actualizar a RC4 y no hice ni un solo cambio en ninguno de mis componentes además de configurar un nuevo enrutador y encontré este problema. Todo estuvo bien en RC1, parece que esto todavía está por ahí.

Más información:

Resulta que debido a la llamada async dentro de ngOnInit , se produce este error. Si comento el código de llamada asíncrona o muevo ese fragmento de código al constructor, todo funciona bien.

@ ammar91
Llame a esto después de los cambios:
changeDetectionRef.detectChanges ()

@ zigzag95 Sí, esta es una solución alternativa, pero se siente súper hack hacer esto. Esperaría que un marco como angular manejara esto de manera más elegante en lugar de hacernos activar manualmente su propio mecanismo de detección de cambios.

En mi caso, está sucediendo cuando me suscribo al emisor de eventos angulares en app.component.ts para mostrar y ocultar la barra de progreso. Todo fue bien con RC1 pero rompió en RC4.

Aquí está la reproducción, http://plnkr.co/edit/jEtfUrQdc4sJBySj5kWN?p=preview
Haga clic en Heroes Link y seleccione uno de los héroes para editar y verá el error.
Consulte los cambios en app.component.ts y hero.service.ts

Hola @vicb , gracias por la actualización. ¿Puede decirnos qué acciones se han tomado? ¿Quiere decir que esto se solucionará en la próxima versión?

Otra solución alternativa simple que funcionó para mí es devolver el valor como observable y retrasar la emisión de valores en 10 ms. En mi caso, la excepción se produjo con el valor de la ruleta.
<app-spinner *ngIf="spinner"></app-spinner>

  this.eventService.toggleSpinnerAnnounced$.subscribe(
      (show: boolean) => this.spinner = show
    );

esto funcionó para mí:

private spinner = new Subject<boolean>();
toggleSpinnerAnnounced$ = this.spinner.asObservable().delay(10); // This  delay() is important

announceSpinnerToggle(show: boolean) {
        this.spinner.next(show);
    }

Esto funcionó para usted porque está usando el retraso y no está relacionado con lo observable.
Tendrá el mismo comportamiento cuando use stettimeout.

@Jarvens, por favor deje de publicar este comentario en lugares inapropiados.

Los problemas de GitHub son para informes de errores y solicitudes de funciones.
Para preguntas de soporte, utilice otros canales como los que se enumeran en CONTRIBUYENDO: ¿Tiene alguna pregunta o problema?

Su comentario no proporciona suficiente información para diagnosticar su problema.

FYI: Recibí este error debido a la extensión de Chrome ng-inspector for AngularJS (alternativa de extensión angular 1 a batarang)

¡Esto es una locura! Después de leer todo el hilo, lo que solucionó el problema en el modo de desarrollo fue deshabilitar ng-inspector para AngularJS como dice @ KarlGustav-unimicro.

Dicho esto, ChangeDetectorRef.detectChanges() también funcionó para mí, pero me sentí realmente hack.

@ pkozlowski-opensource,
Todavía no tengo idea de por qué se invocará indicatorStyle() cuando cambie una de las entradas,
¿Puedes dar más explicación?
Si implemento ngDoCheck en _progress-bar component_ sin configurar ChangeDetectionStrategy.OnPush en el componente principal,
descubrí que ngDoCheck ejecución dos veces,
sé por qué se ejecutará el primero,
pero realmente estoy confundido sobre el segundo ngDoCheck ...

http://plnkr.co/edit/myX2Alx9jie2q0FDIME7?p=preview

@LiTiang ,

Todavía no tengo idea de por qué se invocará indicadorStyle () cuando cambie una de las entradas,
¿Puedes dar más explicación?

Dado que indicatorStyle() está vinculado a [ngStyle] en la vista, siempre se invocará cuando se ejecute el detector de cambios. Esto sucederá independientemente de si las entradas han cambiado o no.

descubrí que la ejecución de ngDoCheck dos veces,
sé por qué se ejecutará el primero,
pero estoy realmente confundido sobre el segundo ngDoCheck ...

Lo más probable es que esto se deba a que, como se mencionó anteriormente en este hilo, la detección de cambios siempre se ejecuta dos veces en el modo de desarrollo. Hace esto para verificar que no tenemos código que cambie los enlaces durante la detección de cambios, lo que podría causar errores difíciles en la producción.

Una variación de setTimeout ()

ACTUALIZACIÓN: La CPU se volvió 100% loca sin compañero Altura Última comparación: AFAIK ¡Las actualizaciones se volvieron recursivas!

ACTUALIZACIÓN2: Ejemplo de Plunker

Quería la altura de un bloque dinámico <ul> para controlar la altura de un <img> que he vinculado a "companionHeight".

Tan malvado ... Pero lo siguiente funciona usando un Observable.

Aquí está el elemento <ul> cuya altura se está monitoreando:

<ul class="title-list-ul" #listul (window:resize)="setCompanionHeight(listul)">

Aquí está el elemento <img> que se está controlando:

<img class="title-list-companion-img" [src]="getCompanionImageURL()" [height]="companionHeight"/>

Estos son los métodos de componentes que interactúan:

import { Component, OnInit, AfterViewChecked, ElementRef } from '@angular/core';  // redacted
import { Observable } from 'rxjs';

@Component({
  selector: 'resume-title-list',
  templateUrl: './title-list.component.html',
  styleUrls: ['./title-list.component.scss']
})
export class TitleListComponent implements OnInit, AfterViewChecked {

  private error: Object;
  private companionHeight: number = 0;
  private companionHeightLast: number = 0;

   // Lots of irrelevant stuff like ngInit redacted for simplicity.

  constructor(private elementRef: ElementRef) { }  // redacted, mine is more complicated.

  setCompanionHeight(listElement: any) {
    let clientRect = listElement.getBoundingClientRect();
    if (clientRect) {
      this.companionHeight = clientRect["height"];
    }
  }

  // window::resize only happens when the window is resized: This is an initialization 
  // function that sets the initial size of the image... Without it the image height is 
  // initially zero and the image is not shown. 
  // The height was not correct in ngAfterViewInit, so I used ngAfterViewChecked instead.

  ngAfterViewChecked() {
    let ularray = this.elementRef.nativeElement.getElementsByClassName("title-list-ul");
    if (ularray && ularray.length > 0) {
        let h = ularray[0].getBoundingClientRect().height;
        if (h && h != this.companionHeightLast) {
          this.companionHeightLast = h;
          Observable
          .of(h)
          .delay(10)
          .subscribe(h => this.companionHeight = h,
                     error => this.error = error);
        }
    }
  }
}

Es posible que los miembros del equipo de Angular no lean los comentarios sobre problemas cerrados.
¿Qué tal publicar una pregunta en uno de estos canales? CONTRIBUYENDO: ¿Tiene una pregunta o un problema? con un Plunker para reproducir?

Tuve el mismo problema con:

<div *ngIf="isLoading">
   <app-some-viewchild></app-some-viewchild>
</div>

Usin [oculto] en lugar de * ngSi resuelve el problema.

También me encontré con este problema. Finalmente, descubrí que el objeto de inicio predeterminado es el mismo que el objeto ngModle.

configurar el changeDetection: ChangeDetectionStrategy.OnPush en el @Component decorador lo arregló para mí

@elvismercado gracias, resuelve mi problema en 2.1.1!

Tenía un componente secundario que dependía de un valor pasado por la plantilla principal, y la plantilla secundaria lanzaba esta excepción cuando cambiaba el valor principal. Agregar su sugerencia al componente secundario hace que la detección de cambios no se ejecute hasta que el valor cambiado se envíe al componente secundario, evitando que la detección se ejecute prematuramente, supongo.

Si tengo una entrada que tiene el foco y luego la elimino del DOM (condición ngIf), aparece el error "La expresión ha cambiado después de que se verificó" (solo si la entrada tiene un grupo de formularios asociado).
Aquí hay un plunker con el problema:
https://plnkr.co/edit/dooRvC1gY1WEcaNdshoP?p=preview
¡Gracias!

Entonces, ¿cuál es la solución aquí?

Cambiar cualquier valor de entrada en ngOnInit activará esto.

@coli
solo envuélvete en

setTimeout(()=>{
 ///your code here
}, 1);

Tengo una combinación de componentes secundarios que deben cargarse previamente cuando un usuario desea editar una entidad existente.
He estado luchando con este problema durante horas hasta que logré solucionarlo usando la publicación de @drewlio anterior.

Inyectar _changeDetectionRef:

    constructor(
        private _changeDetectionRef: ChangeDetectorRef) {
    }

Y luego, justo después de realizar su llamada de cambio, detectar cambios.
Esto funcionó para mí.

    setSizeFromCtrl() {
        console.log("setSizeFromCtrl");
        if (this.sizeFromList && this.tradeProfile && this.tradeProfile.SizeFrom && this.sizeFromCtrl) {
            this.sizeFromCtrl.select(String(this.tradeProfile.SizeFrom));
            this._changeDetectionRef.detectChanges();
            console.log("setSizeFromCtrl DONE");
        }
    }

    setCentreTypeCtrl() {
        console.log("setCentreTypeCtrl");
        if (this.centreTypeList && this.tradeProfile && this.tradeProfile.centreTypeList && this.centreTypeCtrl) {

            for (let i of this.tradeProfile.centreTypeList) {
                this.centreTypeCtrl.select(i.value);
            }
            this._changeDetectionRef.detectChanges();
            console.log("centreTypeCtrl DONE");
        }
    }


Tenga en cuenta que tuve este mismo problema pero una causa diferente (¿similar?) Y diferentes soluciones.

  • Nuestra aplicación Angular - https://github.com/GeoscienceAustralia/GNSS-Site-Manager , tiene formas reactivas modelo que están anidadas y construidas en múltiples componentes en ngOnInit() . Algunos de estos formularios están contraídos con un ngIf en la plantilla
  • Los datos también se leen en un ngOnInit() y se estaban aplicando con un theModelForm.patchValue(data)
  • Este error apareció cuando se expandió uno de los formularios contraídos. Está relacionado con el hecho de que el DOM no se creó porque el formulario se creó en ngOnInit() que no se activó hasta que se expandió. Saque el patchValue() y el problema desapareció
  • Se nos ocurrieron dos soluciones
  • Antes del patchValue() ejecute un this._changeDetectionRef.detectChanges(); . Y cambie ngIf a [hidden] para que el formulario y el DOM estén completamente construidos. La desventaja de esto es el tiempo y el costo de memoria a medida que se crea el formulario completo y el DOM relacionado (esto puede no ser un problema en muchas aplicaciones, pero lo fue para nosotros, ya que tenemos un formulario gigantesco).
  • La mejor solución es aplicar patchValue() (o setValue() si los datos y los campos son 1: 1) en los componentes y, por lo tanto, solo sucede cuando el formulario se crea en ngOnInit() .

Aún no he realizado estos cambios (22/3/17).

Por eso no creo que esta decisión salve a todos.
Pero en mí, la aparición del error dado fue acompañada por la creación de un nuevo elemento de una clase. Luego, agréguelo a la matriz, que se genera a través de * ngFor.
Resolví este problema agregando un constructor a mi clase, que llenó los campos requeridos para mostrar en la plantilla los valores predeterminados (ceros, líneas vacías)

export class Task {
    task_id: number;
....
    constructor() {
        this.task_name = '';
        this.task_desc = '';
        this.task_percent = 0;
  addNewTask():void{
    let newTask = new Task();
    this.tasksList.push(newTask);
  }

task_name & task_desc & task_percent que estoy mostrando en la plantilla. Si al menos uno de los campos enumerados no está inicializado en el constructor, aparece un error similar.

+1

Trabajo de la solución AerisG222

constructor(private _changeDetectionRef : ChangeDetectorRef) { }

ngAfterViewInit() : void {
    // your code

    this._changeDetectionRef.detectChanges();
}

this._changeDetectionRef.detectChanges () funciona, pero causará otros problemas en mi caso. Simplemente envuelvo el código dentro de la función setTimeout (), lo resuelve.

@GuofuHuang hacer eso es una forma de evitar el problema, no solucionarlo, lo que a veces puede conducir a ciclos infinitos de detección de cambios.

@Toxicable Lo siento, probablemente no lo dejé claro, no estoy usando this._changeDetectionRef.detectChanges (); En cambio, envuelvo mi código fuente dentro de setTimeout ().

@GuofuHuang, si lo que pones dentro de setTimeout causa CD y lo estás ejecutando en un enlace de ciclo de vida, entonces es posible que estés provocando ciclos de CD infinitos. La solución no es realizar cambios que provoquen el CD durante la ejecución de un CD

@Toxicable ¿ Incluso lo puse en 0?

@GuofuHuang si el ajuste a 0 provoca un CD, entonces sí

@Toxicable Acabo de encontrar este enlace, http://stackoverflow.com/questions/779379/why-is-settimeoutfn-0-sometimes-useful , dice que setTimeout de 0 es algo así como pausa / rendimiento en C, no ' No sé si causará algún CD, pero ahora funciona perfecto en el mío. Si no es esta solución, ¿tiene una mejor para resolver este problema?

@GuofuHuang No sé qué hace la pausa / rendimiento en C, pero en JS colocará la devolución de llamada al final de la cola de eventos. Mi solución es la anterior: la solución no es realizar cambios que provoquen el CD durante la ejecución de un CD

settimeout es la solución
No es necesario que especifique el parámetro ms y esperaré un tic

@ zigzag95 @GuofuHuang vea este ejemplo de por qué setTimeout no es la solución
https://plnkr.co/edit/dv8K9EvVQLG59Gxsl3oI?p=preview

@Toxicable Gracias, pero mi caso es muy diferente a este, y no veo ningún bucle infinito. Pero este es definitivamente un buen ejemplo que me ayuda a comprender más angular.

@GuofuHuang De hecho, no sucederá en tu caso porque lo estás haciendo en ngAfterViewInit que solo se llama una vez. Mi punto fue que es posible causar un bucle infinito con este método, por lo tanto, es peligroso de usar. Eso es lo que muestra el plunkr.

@moutono ¡ Tus trucos me han ayudado! Muchas gracias 😄

Como el problema consiste en activar la detección de cambios, la resolución de una promesa también podría funcionar porque ngZone monkey patches también promete. Este me ha funcionado:

ngAfterViewInit() {
  Promise.resolve().then(() => your_code_here);
}

Sí, setTimeout funciona, pero no me gustó esa solución, en mi caso se debió a que estaba cambiando el valor en un EventEmitter
La solución fue el cambio
private generalSubscriber: EventEmitter<any> = new EventEmitter<any>();
para
private generalSubscriber: EventEmitter<any> = new EventEmitter<any>(true);

raro ¿verdad?
Bueno, eso significa verdadero, el emisor de eventos es asincrono
https://angular.io/docs/ts/latest/api/core/index/EventEmitter-class.html

¿Hay alguna solución para esto? ¿Por qué está cerrado?

Tengo que borrar el caché cada vez

en mi caso, estaba reemplazando un código auxiliar de imagen al cargar la imagen, tuve que ponerlo en un setTimeout

@intergleam @ @ wasa4587 caroso1222 @tandu @ @ @robwormald @ @ @pcroc @zoechi @stefankoru @bennadel @bryanforbes @Necroskillz @drewlio @ElsewhereGames @zoechi @ user414 @ e-oz

Se enfrenta al error durante el desarrollo. En el servidor de producción funcionando bien.

@smartHasmukh es un error solo en modo de desarrollo, por lo tanto, no es de extrañar.
Aún deberías arreglarlo.

Si ocurre este error, lo más probable es que rompa el flujo de datos en una dirección. Lo que podría ser algo como cambiar los datos de un componente en el hermano, cambiar los datos de los padres en los ganchos del ciclo de vida de los hijos, tal vez algo más.
Esta excepción lanzada no es un error, sino una ayuda para que el desarrollador comprenda que el contrato de flujo de datos en una dirección está roto de alguna manera. El hecho de que esto funcione en producción es por accidente, debe revisar cómo está cambiando sus datos en la comunicación entre padres e hijos y corregirlo en el modo de desarrollo.

@smartHasmukh Esto resultaba incómodo. Por ejemplo, engancho a los eventos de navegación y luego emito un evento al componente principal para mostrar un cargador. Y en cada componente oculto ese cargador, después de recibir los datos del servidor (es decir, dentro de una suscripción). Esta bien. Pero, en un componente, solo obtuve algunos datos de una fuente "estática", no observable allí, así que simplemente intenté usar ngOnInit para decirle al componente principal que ocultara el cargador. Entonces obtuve el error, por supuesto.

Aunque mi caso debería ser algo simple, no es la forma correcta de hacerlo. Tuve que tomar la decisión de no mostrar el cargador en primer lugar, para ese componente (lo que podría volverse más complicado si tuviera más componentes como ese) ... O también manejar ocultar el cargador de mi servicio de datos , en lugar de a nivel de componente. O, una solución fea, sería envolver ese caso específico en un setTimeout (). Porque el enfoque inicial no fue el correcto.

TL / DR:
Estoy seguro de que también tiene que haber una forma adecuada para su escenario, aparte de un _setTimeout () _ solución fea (que _tristemente_ elegí en ese momento, pero, de nuevo, es un escenario muy simple y sé lo que es continúa allí, sin embargo, es posible que tenga que cambiarlo en algún momento, en una versión futura).
Puede probar StackOverflow para su caso específico, dar más detalles. Tiene que haber una forma.

Seguro Gracias @MrCroft @tytskyi y lo haré Sr. @zoechi y sé que no es ninguna sorpresa. pero solo se lo dejo saber. nada más

@tytskyi

El hecho de que esto funcione en producción es por accidente, debes revisar

No, en la mayoría de los casos mi respuesta a este error es "sí, lo sé, y está previsto". Muchos componentes en mis aplicaciones están cargando algo después de init y después de recibir nuevos valores en variables vinculadas. Este problema es simplemente "fealdad conocida" de Angular y a nadie le importa.

@ e-oz si está afectando de alguna manera el estado de padre o hermano en cualquiera de los ganchos del ciclo de vida, entonces esto está rompiendo el flujo de datos en una dirección. Debe realizar estos cambios cuando el estado de la aplicación esté estabilizado, pero no en medio de la detección de cambios. Es por eso que existen esos trucos con microtask, setTimeout 0, etc.

@tytskyi cálmate con tu "debería", estoy haciendo cambios después de la estabilización - es obvio si se lee con atención - la solicitud http para cargar datos adicionales, obviamente, tomará más tiempo que la estabilización inicial. No me vas a convencer de que este comportamiento de Angular es correcto, ni lo intentes.

@ e-oz ¿cómo se relaciona eso con una solicitud HTTP? Una respuesta de solicitud HTTP provoca la detección de cambios y no obtendrá el error "La expresión ha cambiado ...".
¿Puede proporcionar más información?

@zoechi no hay razón para perder el tiempo en eso, nadie cambiará nada, la tarea está cerrada.

@ e-oz, el problema se cerró hace un año y el equipo de Angular tenía prioridades bastante diferentes en ese entonces (obtener un lanzamiento) y este problema no era un bloqueador en ese entonces.
Si cree que tiene un caso válido, debe crear un nuevo problema.

@zoechi No creo que tú decidas lo que debo hacer. Puedo crear un nuevo problema, pero no es necesario. Con todo respeto, no me gusta ese tono de "deberías".

@ e-oz Ya veo, sus comentarios son solo para desahogar su frustración y no está interesado en obtener una solución. Por favor, deje de perder el tiempo de otras personas aquí con sus comentarios inútiles.

si está llamando a http, suscríbase a su componente, solo agregue ..
Promise.resolve().then(() => your_code_here);
o
myObservable.delay(10).subscribe(...)

Una de las dos soluciones resolverá su problema.

@vicb Deje de cerrar los problemas que no están solucionados. Por qué estás haciendo esto ?

Al menos sugiera una solución adecuada, pero cerrar esto es inaceptable

@diegogarciaa ... y ¿qué es exactamente lo que no está arreglado o está mal desde tu punto de vista? La conversación ^^^ es tan larga que es difícil encontrar el núcleo real.

@ mlc-mlapis con el debido respeto, no soy tu maestro, si no puedes leer o entender el problema, deja de molestarte. Pasé largos minutos leyendo todo el contenido, recomiendo lo mismo.

La actitud del equipo angular (no todo el equipo, pero que están aquí cerrando este tema) parece tan emprendedora: no bloquear (mi salario), no arreglarlo pronto.

@diegogarciaa ... muy bueno. Continúe como arriba y será bienvenido en todas partes.

@ mlc-mlapis No quiero ser bienvenido donde la gente no puede leer y tratar de hacer tonterías donde no debería.

@diegogarciaa ... Solo pensé que tú personalmente tienes un problema y parece que ahora no es cierto. Y la realidad también es que la mayoría de los problemas con Expression has changed after it was checked ... no son errores, sino que no comprenden bien cómo funciona el CD.

@ mlc-mlapis ok ... entendamos

http://plnkr.co/edit/nm8OkrpZCIp4cvA6TbpO?p=preview

En este plunk, puedo entender que la variable estaba vinculada y verificada cuando se llamó a ngAfterViewInit, por lo tanto, cuando recibe un nuevo valor y no activa una nueva ronda de verificación, se lanzan las excepciones

Pero, por ejemplo, si tengo una referencia de contenedor de vista ... y uso, por ejemplo:

this.service.GetData (). subscribe (
respuesta => this.component.instance.dataModel = respuesta
);

Tenga en cuenta que dataModel se está utilizando como {{dataModel.Field}} en mi html

this.component es un componente dinámico que se carga en ciertos eventos, ¿cómo se podría evitar el error? ¿Cuál sería la forma correcta de pasar los datos a mi componente antes de los ganchos del ciclo de vida de la detección de cambios?

@diegogarciaa ... sí, este es un ejemplo típico donde la operación asíncrona y sincronizada se mezclan y se encuentran en un CD y su confirmación en modo dev. No repetiré la explicación de la publicación https://hackernoon.com/everything-you-need-to-know-about-the-expressionchangedafterithasbeencheckederror-error-e3fd9ce7dbb4 , así que tal vez intente leerlo primero.

Y busque también https://hackernoon.com/here-is-how-to-get-viewcontainerref-before-viewchild-query-is-evaluate-f649e51315fb.

Entonces, el artículo básicamente dice que debo llamar manualmente a una ronda de detección de cambios ...

Seamos honestos, estoy muy molesto con el estado actual ... incluso las cosas mínimas en angular son tan aburridas y agotadoras ... ni siquiera puedo respirar. Vete a la mierda

@diegogarciaa ... no, es solo una solución auxiliar. También puede usar promise.then o usar setTimeout ... pero la solución recomendada en este caso es probablemente un servicio compartido, por lo que no actualizará directamente la propiedad del componente dinámico cruzando el ciclo del CD y su confirmación.

O simplemente cree una instancia del componente dinámico en el momento en que tendrá los datos. Entonces, su suscripción invocará la creación de la instancia del componente dinámico.

Pero lo que es importante -> la lógica principal por la que ocurre el error -> porque los cambios unidireccionales deben fluir siempre de arriba hacia abajo a través de todo el árbol y después de un ciclo de CD hay una confirmación del estado de que se respetó el principio unidireccional.

Este "vete a la mierda" no era personal ... solo desahogaba mis frustraciones.

Usamos un esquema de directiva para manejar nuestros componentes. Creamos un ayudante que carga un componente en una referencia de vista de componente y, como entendemos, los datos deben estar disponibles cuando se carga un componente.

protected loadPartialView(viewName: string, target: ViewContainerRef) : ComponentRef<any> {
        const factories = Array.from(this.resolver['_factories'].keys());
        const factoryClass = <Type<any>>factories.find((x: any) => x.name === viewName);
        const factory = this.resolver.resolveComponentFactory(factoryClass);
        return target.createComponent(factory);
}

En el ejemplo anterior: me gustaría hacer algo como esto:

return target.createComponent(factory, dataSource);

Donde mi fuente de datos estaría disponible en el momento del constructor

Al igual que redux, que usa un objeto para manejar la fuente de datos que pasa a través de los componentes, estamos pensando en implementar un componente inyectable que maneje los datos por nosotros, para que podamos obtenerlos antes de que el ciclo de vida se enganche.

diegogarciaa

No creo que los datos deban estar disponibles antes ... un componente dinámico sigue siendo un componente con @Input() y @Output() pero la pregunta es cuándo cambiará los datos.

... los datos deben estar disponibles cuando se carga un componente ...

Supongo que debe usar también componentes de módulos cargados de forma diferida, por lo que uso un mapa directamente en un módulo para tener la posibilidad de acceder a los componentes usando solo nombres de cadena.

export default class LazyLoadedModule {
    cmps: Map<{}, {}> = new Map();
    constructor() {
        this.cmps.set('first-component', FirstComponent);
        ...
    }
}

¿Qué debería significar return target.createComponent(factory, dataSource); ? Porque la API real es createComponent(componentFactory, index, injector, projectableNodes, ngModule) .

Y tal vez el nuevo módulo @ angular / cdk sea interesante para ti. Solo intro aquí: https://medium.com/@caroso1222/a -first-look-into-the-angular-cdk-67e68807ed9b.

Por lo que vale y si puede ayudar a alguien, en lugar de usar setTimeout y como usar ChangeDetectorRef.detectChanges() no funcionó para mí, terminé usando NgZone.onStable y ejecuté mi código suscribiéndote una vez en el EventEmitter ...

constructor(
  private zone: NgZone,
) { }

ngAfterViewInit() {
  this.zone.onStable.first().subscribe(() => {
    // your code here
  });
}

No soy del todo consciente de las consecuencias de hacer esto, pero ¿puede ser peor que usar setTimeout ? Si alguien tiene algún comentario al respecto, ¡sería bienvenido!

La solución

constructor(private _changeDetectionRef : ChangeDetectorRef) { }

ngAfterViewChecked() : void {
    // your code
    this._changeDetectionRef.detectChanges();
}

este es el componente html:

{{lastData.note [i] .date | fecha: 'dd.MM.yyyy'}} | {{lastData.note [i] .date | fecha: 'HH: mm'}}:# BFL15_200817 | {{lastData.status.name}} por {{lastData.note [i] .admin}}

Recibí el error si los datos en la matriz son más de uno, ¿alguna solución?

Este es ciertamente un problema complejo, pero para algunos casos (especialmente cuando está modificando propiedades en un ContentChild) se puede resolver moviendo la lógica a ngAfterContentInit () en lugar de ngAfterViewInit () o ngOnInit ()

Es asombroso cómo las cosas simples pueden causar tanta confusión en angular

No te preocupes, todos los demás también lo han notado 😕
image

@jakeNiemiec trabajo lamentable, troll, ya nadie está buscando Angularjs
https://trends.google.com/trends/explore?date=all&q=Angular%20tutorial , React% 20tutorial
image

Sí, esperaría que más gente necesitara buscar en Google "tutorial angular" por desesperación, de ahí el comentario inicial sobre "confusión".

Pero no se preocupe, podemos verificar npm para obtener estadísticas de uso exactas: http://www.npmtrends.com/react-vs-@angular/cli -vs-vue-vs- @ angular / core
image
image

Simplemente compare la cantidad de problemas. Realmente me gustaría que angular mejorara, pero sospecho que Vue.js lo pasará en un futuro lejano. Habiendo programado en los 3, recomiendo Vue a los desarrolladores angulares. Es como angular sin el texto estándar.

ok respuesta aceptada, estoy perfectamente bien con esas estadísticas.
Me imagino que hay más personas que usan PHP en India que Java en todo el mundo. Sería un idiota usar PHP para una aplicación empresarial a gran escala, por lo que debería usar su propio cerebro a veces, la vida será mejor

@jakeNiemiec ... el 50% de los problemas que se crean se colocan por error allí ... son problemas de soporte / conocimiento de hecho y no deberían estar allí en absoluto. Lo divertido es que la mayoría de los temas requeridos están muy bien documentados en los documentos oficiales + las respuestas se basan en el conocimiento de JavaScript. Pero ya sabes, la gente no lee los documentos con la suficiente profundidad.

@HostBinding puede ser una fuente confusa de este error.

Considere un enlace simple en un componente, como @HostBinding('style.background') .

Esa propiedad es verificada por la detección de cambios del componente * padre * como si fuera su 'dueño'. Desde nuestra perspectiva, queremos pensar en él como el componente hijo que 'posee' esa propiedad.

Entonces, ¿parece que debería haber una forma de que un componente excluya propiedades para verificar en este caso? ¿O es más complicado que eso?

Tuve que hacer que mi componente principal ejecutara detectChanges (o agregar un div adicional en el niño) para evitar el error en el caso de que el componente secundario simplemente cambiara su propio color de fondo (y nunca lo hiciera en ningún otro lugar) .

Descripción más completa: https://stackoverflow.com/questions/43375532/expressionchangedafterithasbeencheckederror-explained/51662105#51662105

Solo necesita hacer algo, cualquier cosa, que desencadene otra ronda de detección de cambios durante ese método: emitir un evento, lo que sea. Envolverlo en un tiempo de espera (cola de retroceso en ng1 :-P) es una forma en que funcionaría, pero me parece muy complicado en ng2.

En angular 4, eso trabaja 4 me <3

Este problema se ha bloqueado automáticamente debido a la inactividad.
Por favor, presente un nuevo problema si se encuentra con un problema similar o relacionado.

Obtenga más información sobre nuestra política de bloqueo automático de conversaciones .

_Esta acción ha sido realizada automáticamente por un bot._

¿Fue útil esta página
0 / 5 - 0 calificaciones