ExpressionChangedAfterItHasBeenCheckedError Explicado


308

Explícame por qué sigo recibiendo este error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.

Obviamente, solo lo obtengo en modo de desarrollo, no sucede en mi versión de producción, pero es muy molesto y simplemente no entiendo los beneficios de tener un error en mi entorno de desarrollo que no aparecerá en prod. -probablemente debido a mi falta de comprensión.

Por lo general, la solución es bastante fácil, solo envuelvo el error que causa el código en un setTimeout como este:

setTimeout(()=> {
    this.isLoading = true;
}, 0);

O forzar la detección de cambios con un constructor como este constructor(private cd: ChangeDetectorRef) {}:

this.isLoading = true;
this.cd.detectChanges();

Pero, ¿por qué me encuentro constantemente con este error? Quiero entenderlo para poder evitar estas soluciones hacky en el futuro.


Respuestas:


121

Tuve un problema similar En cuanto a la documentación de los ganchos del ciclo de vida , he cambiado ngAfterViewInita ngAfterContentInity funcionó.


@PhilipEnc mi problema estaba relacionado con un cambio desencadenado por el cambio DOM. Cuando el DOM cambiaría, el objeto QueryList (que provenía de una propiedad @ContentChildren) se actualizaría, y dentro del método que la actualización llamó cambió la propiedad de enlace bidireccional. Esto creó el problema que estaba teniendo. Ajustar ese cambio a la propiedad de dos con setTimeoutcomo muestra arriba hizo el truco. ¡Gracias!
kbpontius

1
En mi caso, coloqué un código que cambió el valor de la matriz de cuadrícula primeng en ngAfterContentInit, coloqué el código en ngOnInit y funcionó.
Vibhu

ngAfterContentCheckedfunciona aquí mientras ngAfterContentInitaún arroja error.
ashubuntu

ngAfterContentChecked uso pero proyecto cargado muy lento
Ghotekar Rahul

101

Este error indica un problema real en su aplicación, por lo tanto, tiene sentido lanzar una excepción.

En devMode detección de cambios, se agrega un giro adicional después de cada ejecución de detección de cambios regular para verificar si el modelo ha cambiado.

Si el modelo ha cambiado entre el turno de detección de cambio regular y el adicional, esto indica que

  • la detección de cambios en sí ha causado un cambio
  • un método o getter devuelve un valor diferente cada vez que se llama

ambos son malos, porque no está claro cómo proceder porque el modelo podría nunca estabilizarse.

Si Angular ejecuta la detección de cambios hasta que el modelo se estabilice, podría ejecutarse para siempre. Si Angular no ejecuta la detección de cambios, entonces la vista podría no reflejar el estado actual del modelo.

Consulte también ¿Cuál es la diferencia entre el modo de producción y desarrollo en Angular2?


44
¿Cómo puedo evitar ver este error en el futuro? ¿Hay alguna forma diferente en la que deba pensar en mi código para asegurarme de no cometer los mismos errores?
Kevin LeStarge

25
Por lo general, esto es causado por algunas devoluciones de llamada del ciclo de vida como ngOnInito ngOnChangespara modificar el modelo (algunas devoluciones de llamada del ciclo de vida permiten modificar el modelo, otras no, no me recuerdo exactamente cuál hacer o no). No se vincule a métodos o funciones en la vista, en lugar de hacerlo, a campos y actualice los campos en los controladores de eventos. Si debe vincularse a los métodos, asegúrese de que siempre devuelvan la misma instancia de valor siempre que no haya realmente un cambio. La detección de cambios llamará mucho a estos métodos.
Günter Zöchbauer

Para cualquiera que llegue aquí y reciba este error usando la biblioteca ngx-toaster, aquí está el informe de error: github.com/scttcper/ngx-toastr/issues/160
rmcsharry

2
No es necesariamente un problema con la aplicación. El hecho de que llamar changeRef.detectChanges()es una solución / suprime el error, es prueba de ello. Es como modificar el estado $scope.$watch()en Angular 1.
Kevin Beal

1
No conozco Angular 1 demasiado bien, pero la detección de cambios en Angular 2 funciona de manera bastante diferente. Tienes razón en que no es necesariamente un problema, pero generalmente cdRef.detectChanges()solo es necesario en algunos casos extraños y debes mirar cuidadosamente cuando lo necesites para entender bien por qué.
Günter Zöchbauer el

83

Mucho entendimiento llegó una vez que entendí los Angular Lifecycle Hooks y su relación con la detección de cambios.

Estaba tratando de hacer que Angular actualizara una bandera global vinculada a *ngIfun elemento, y estaba tratando de cambiar esa bandera dentro del ngOnInit()gancho del ciclo de vida de otro componente.

Según la documentación, se llama a este método después de que Angular ya haya detectado cambios:

Llamado una vez, después de los primeros ngOnChanges ().

Por lo tanto, actualizar el indicador dentro de ngOnChanges()no iniciará la detección de cambios. Luego, una vez que la detección de cambios se ha activado naturalmente nuevamente, el valor de la bandera ha cambiado y se produce el error.

En mi caso, cambié esto:

constructor(private globalEventsService: GlobalEventsService) {

}

ngOnInit() {
    this.globalEventsService.showCheckoutHeader = true;
}

A esto:

constructor(private globalEventsService: GlobalEventsService) {
    this.globalEventsService.showCheckoutHeader = true;
}

ngOnInit() {

}

y solucionó el problema :)


3
Mi problema fue similar. Cometí un error después de largas horas y definí una variable fuera de la función ngOnInit y el constructor. Esto recibe cambios de datos de un observable, que se coloca en la función de inicialización. Hizo lo mismo que tú para corregir el error.
ravo10

1
Muy similar en todas partes, pero estaba tratando de desplazarme ( router.navigate) al cargarlo en un fragmento si estaba presente en la URL. Este código se colocó inicialmente en el lugar AfterViewInitdonde recibía el error, luego me moví como le dijiste al constructor, pero no estaba respetando el fragmento. Pasando a ngOnInitresolverse :) gracias!
Joel Balmer

¿Qué sucede si mi html está vinculado a un tiempo de retorno de getter como "HH: MM" a través de get ClockValue () {return DateTime.TimeAMPM (new Date ())} eventualmente se disparará cuando cambien los minutos mientras se ejecuta la detección, ¿cómo puedo? ¿arregla esto?
Meryan

Igual que aquí. También se descubrió que el ajuste setInterval()también funciona si necesita dispararse después de otro código de evento de por vida.
Rick Strahl

39

Actualizar

Recomiendo encarecidamente comenzar primero con la respuesta propia del OP : piense correctamente en lo que se puede hacer en constructorcomparación con lo que se debe hacer en ngOnChanges().

Original

Esto es más una nota al margen que una respuesta, pero podría ayudar a alguien. Me topé con este problema al intentar hacer que la presencia de un botón dependiera del estado del formulario:

<button *ngIf="form.pristine">Yo</button>

Hasta donde yo sé, esta sintaxis hace que el botón se agregue y elimine del DOM según la condición. Lo que a su vez conduce a la ExpressionChangedAfterItHasBeenCheckedError.

La solución en mi caso (aunque no pretendo comprender todas las implicaciones de la diferencia), fue usar display: noneen su lugar:

<button [style.display]="form.pristine ? 'inline' : 'none'">Yo</button>

66
Entiendo que la diferencia entre el ngIf y el estilo es que el ngIf no incluye el HTML en la página hasta que la condición sea verdadera, lo que reduce un poco el "peso de la página", mientras que la técnica del estilo hace que el HTML sea siempre en la página y simplemente se oculta o se muestra según el valor de form.pristine.
user3785010

44
También podría usar en [hidden]lugar de la parte muy detallada [style.display]. :)
Philipp Meissner

2
Por qué no. Aunque, como lo menciona @Simon_Weaver en otro comentario en esta página, [hidden] no siempre tendrá el mismo comportamiento quedisplay: none
Arnaud P

1
Estaba mostrando dos botones diferentes (cerrar sesión / iniciar sesión) con * ngIf en cada botón y esto estaba causando el problema.
GoTo

constructor fue el lugar adecuado para mí, lanzando un material snack-bar
austin

31

Hubo respuestas interesantes, pero no encontré una para satisfacer mis necesidades, la más cercana de @ chittrang-mishra, que se refiere solo a una función específica y no a varios conmutadores como en mi aplicación.

No quería usar [hidden]para aprovechar *ngIfni siquiera ser parte del DOM, así que encontré la siguiente solución, que puede no ser la mejor para todos, ya que suprime el error en lugar de corregirlo, pero en mi caso, donde sé el El resultado final es correcto, parece estar bien para mi aplicación.

Lo que hice fue implementar AfterViewChecked, agregar constructor(private changeDetector : ChangeDetectorRef ) {}y luego

ngAfterViewChecked(){
  this.changeDetector.detectChanges();
}

Espero que esto ayude a otros como muchos otros me han ayudado.


3
¿No disparará esto un bucle de detección de cambio infinito? Quiero decir, estás detectando cambios después de haber verificado.
Manuel Azar

@ManuelAzar Aparentemente no lo hace. Esta es la ÚNICA solución que funcionó para mí. Por fin un poco de silencio en mi consola. Estaba tan cansado de todos estos "errores" irrelevantes de detección de cambios.
Jeremy Thille

31

Angular ejecuta la detección de cambios y cuando encuentra que algunos valores que se han pasado al componente secundario han cambiado, Angular arroja el error:

ExpressionChangedAfterItHasBeenCheckedError haga clic para más

Para corregir esto, podemos usar el AfterContentCheckedgancho del ciclo de vida y

import { ChangeDetectorRef, AfterContentChecked} from '@angular/core';

  constructor(
  private cdref: ChangeDetectorRef) { }

  ngAfterContentChecked() {

    this.cdref.detectChanges();

  }

Aunque esto podría solucionar el problema, ¿no es esto muy expansivo y exagerado el CD?
Nicky

Creo que esta es la única respuesta que aborda este error causado al pasar valores a un niño. ¡Gracias!
java-addict301

@Nicky Sí. Cada vez que toca en la pantalla, en cualquier lugar, se llama ngAfterContentChecked ()
Mert Mertce

25

En mi caso, tuve este problema en mi archivo de especificaciones, mientras ejecutaba mis pruebas.

Tuve que cambiar ngIf a [hidden]

<app-loading *ngIf="isLoading"></app-loading>

a

<app-loading [hidden]="!isLoading"></app-loading>


2
La diferencia aquí es que *ngIfcambia el DOM, agrega y elimina el elemento de la página, mientras que [hidden]cambia la visibilidad del elemento sin eliminarlo del DOM.
Grungondola

55
Pero, ¿esto realmente no solucionó el verdadero problema ...?
ravo10

23

Siga los pasos a continuación:

1. Use 'ChangeDetectorRef' importándolo de @ angular / core de la siguiente manera:

import{ ChangeDetectorRef } from '@angular/core';

2. Impleméntelo en constructor () de la siguiente manera:

constructor(   private cdRef : ChangeDetectorRef  ) {}

3. Agregue el siguiente método a su función que está llamando en un evento como hacer clic en el botón. Entonces se ve así:

functionName() {   
    yourCode;  
    //add this line to get rid of the error  
    this.cdRef.detectChanges();     
}

23

Estaba usando ng2-carouselamos (Angular 8 y Bootstrap 4)

A continuación se solucionó mi problema:

Lo que hice:

1. implement AfterViewChecked,  
2. add constructor(private changeDetector : ChangeDetectorRef ) {} and then 
3. ngAfterViewChecked(){ this.changeDetector.detectChanges(); }

Eso ayudo. ¡¡Asombroso!!
Pathik Vejani

Me salvaste el día ... ¡Gracias!
omostan

19

Estaba enfrentando el mismo problema ya que el valor estaba cambiando en una de las matrices de mi componente. Pero en lugar de detectar los cambios en el cambio de valor, cambié la estrategia de detección de cambio de componente a onPush(que detectará cambios en el cambio de objeto y no en el cambio de valor).

import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';

@Component({
    changeDetection: ChangeDetectionStrategy.OnPush
    selector: -
    ......
})

Esto parecía funcionar para agregar / eliminar dinámicamente los controles ... ¿hay algún inconveniente?
Ricardo Saracino

Funciona como un encanto en la situación que tengo a mano, ¡gracias! Un componente estaba vinculado a un objeto "global" que se cambió en otro lugar y provocó el error. Este componente ya tenía un controlador de actualización para cuando se actualizó el objeto vinculado, este controlador de eventos ahora llama a changeDetectorRef.detectChanges () en combinación con ChangeDetectionStrategy.OnPush, funciona como se desea sin el error.
Bernoulli IT

@RicardoSaracino ¿Encontraste algún inconveniente? Me preguntaba lo mismo. Sé cómo funciona la detección de cambios en OnPush, pero me pregunto si hay un problema que quizás me estoy perdiendo. No quiero tener que dar la vuelta.
mtpultz

@RicardoSaracino, sí, tiene algunos inconvenientes, puede consultar este enlace detallado blog.angular-university.io/onpush-change-detection-how-it-works
Dheeraj

@ BernoulliIT Gracias, me alegro de que te haya funcionado.
Dheeraj

17

En referencia al artículo https://blog.angularindepth.com/everything-you-need-to-know-about-the-expressionchangedafterithasbeencheckederror-error-e3fd9ce7dbb4

Por lo tanto, la mecánica detrás de la detección de cambios en realidad funciona de manera que tanto los resúmenes de detección de cambios como los de verificación se realizan sincrónicamente. Eso significa que si actualizamos las propiedades de forma asincrónica, los valores no se actualizarán cuando se ejecute el bucle de verificación y no obtendremos ningún ExpressionChanged...error. La razón por la que obtenemos este error es que, durante el proceso de verificación, Angular ve valores diferentes de los que registró durante la fase de detección de cambios. Entonces para evitar eso ...

1) Use changeDetectorRef

2) usa setTimeOut. Esto ejecutará su código en otra VM como una macro tarea. Angular no verá estos cambios durante el proceso de verificación y no obtendrá ese error.

 setTimeout(() => {
        this.isLoading = true;
    });

3) Si realmente desea ejecutar su código en la misma VM, use como

Promise.resolve(null).then(() => this.isLoading = true);

Esto creará una microtarea. La cola de micro tareas se procesa después de que el código síncrono actual ha terminado de ejecutarse, por lo tanto, la actualización de la propiedad se realizará después del paso de verificación.


¿Puedes usar la opción # 3 con una expresión de estilo? Tengo una expresión de estilo para la altura que debería evaluarse en último lugar, porque se basa en el contenido inyectado.
N-ate el

1
Lo siento, acabo de ver tu comentario, sí, no veo ninguna razón por la que no. Eso también debería funcionar con los cambios de estilo.
ATHER

4

@HostBinding puede ser una fuente confusa de este error.

Por ejemplo, supongamos que tiene el siguiente enlace de host en un componente

// image-carousel.component.ts
@HostBinding('style.background') 
style_groupBG: string;

Para simplificar, digamos que esta propiedad se actualiza mediante la siguiente propiedad de entrada:

@Input('carouselConfig')
public set carouselConfig(carouselConfig: string) 
{
    this.style_groupBG = carouselConfig.bgColor;   
}

En el componente principal lo está configurando programáticamente ngAfterViewInit

@ViewChild(ImageCarousel) carousel: ImageCarousel;

ngAfterViewInit()
{
    this.carousel.carouselConfig = { bgColor: 'red' };
}

Esto es lo que pasa:

  • Se crea su componente principal
  • El componente ImageCarousel se crea y se asigna a carousel(a través de ViewChild)
  • No podemos acceder carouselhasta ngAfterViewInit()(será nulo)
  • Asignamos la configuración, que establece style_groupBG = 'red'
  • Esto a su vez se establece background: reden el componente host ImageCarousel
  • Este componente es 'propiedad' de su componente principal, por lo que cuando busca cambios, encuentra un cambio carousel.style.backgroundy no es lo suficientemente inteligente como para saber que esto no es un problema, por lo que arroja la excepción.

Una solución es introducir otro contenedor de información privilegiada ImageCarousel y establecer el color de fondo en eso, pero luego no obtendrá algunos de los beneficios del uso HostBinding(como permitir que el padre controle los límites completos del objeto).

La mejor solución, en el componente principal es agregar detectChanges () después de configurar la configuración.

ngAfterViewInit()
{
    this.carousel.carouselConfig = { ... };
    this.cdr.detectChanges();
}

Esto puede parecer bastante obvio como este, y muy similar a otras respuestas, pero hay una sutil diferencia.

Considere el caso en el que no agrega @HostBindinghasta más tarde durante el desarrollo. De repente, obtienes este error y no parece tener ningún sentido.


2

Aquí están mis pensamientos sobre lo que está sucediendo. No he leído la documentación, pero estoy seguro de que esto es parte de por qué se muestra el error.

*ngIf="isProcessing()" 

Cuando se usa * ngIf, cambia físicamente el DOM al agregar o eliminar el elemento cada vez que cambia la condición. Entonces, si la condición cambia antes de que se muestre en la vista (que es muy posible en el mundo de Angular), se produce el error. Vea la explicación aquí entre los modos de desarrollo y producción.

[hidden]="isProcessing()"

Cuando se usa [hidden], no cambia físicamente DOMsino que simplemente lo oculta elementde la vista, lo más probable es que lo use CSSen la parte posterior. El elemento todavía está allí en el DOM pero no es visible dependiendo del valor de la condición. Es por eso que el error no ocurrirá al usar [hidden].


Si isProcessing()está haciendo lo correcto, debe usarlo !isProcessing()para[hidden]
Matthieu Charbonnier

hiddenno "usa CSS en la parte posterior", es una propiedad HTML normal. developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/…
Lazar Ljubenović

1

Para mi problema, estaba leyendo github - "ExpressionChangedAfterItHasBeenCheckedError al cambiar el valor de un componente 'no modelo' en afterViewInit" y decidí agregar el ngModel

<input type="hidden" ngModel #clientName />

Se solucionó mi problema, espero que ayude a alguien.


1
¿Dónde en ese sitio dice agregar ngModel? ¿Y podría explicar por qué esto debería ser útil?
Peter Wippermann

Cuando estaba rastreando este problema, me llevó a investigar el enlace. Después de leer el artículo, agregué el atributo y solucionó mi problema. Es útil si alguien se encuentra con el mismo problema.
Demodave el

1

Consejos de depuración

Este error puede ser bastante confuso, y es fácil hacer una suposición errónea sobre cuándo exactamente está ocurriendo. Encuentro útil agregar muchas declaraciones de depuración como esta en todos los componentes afectados en los lugares apropiados. Esto ayuda a entender el flujo.

En el padre, ponga declaraciones como esta (la cadena exacta 'EXPRESSIONCHANGED' es importante), pero aparte de eso, estos son solo ejemplos:

    console.log('EXPRESSIONCHANGED - HomePageComponent: constructor');
    console.log('EXPRESSIONCHANGED - HomePageComponent: setting config', newConfig);
    console.log('EXPRESSIONCHANGED - HomePageComponent: setting config ok');
    console.log('EXPRESSIONCHANGED - HomePageComponent: running detectchanges');

En las devoluciones de llamada de niño / servicios / temporizador:

    console.log('EXPRESSIONCHANGED - ChildComponent: setting config');
    console.log('EXPRESSIONCHANGED - ChildComponent: setting config ok');

Si ejecuta detectChangesmanualmente, agregue el registro para eso también:

    console.log('EXPRESSIONCHANGED - ChildComponent: running detectchanges');
    this.cdr.detectChanges();

Luego, en el depurador de Chrome, simplemente filtre por 'EXPRESSIONCHANGES'. Esto le mostrará exactamente el flujo y el orden de todo lo que se establece, y también exactamente en qué punto Angular arroja el error.

ingrese la descripción de la imagen aquí

También puede hacer clic en los enlaces grises para colocar puntos de interrupción.

Otra cosa a tener en cuenta si tiene propiedades con nombres similares en toda su aplicación (como style.background) asegúrese de depurar la que cree, configurándola en un valor de color oscuro.


1

En mi caso, tenía una propiedad asíncrona LoadingServicecon un BehavioralSubjectisLoading

El uso del modelo [oculto] funciona, pero * ngIf falla

    <h1 [hidden]="!(loaderService.isLoading | async)">
        THIS WORKS FINE
        (Loading Data)
    </h1>

    <h1 *ngIf="!(loaderService.isLoading | async)">
        THIS THROWS ERROR
        (Loading Data)
    </h1>

1

Una solución que funcionó para mí usando rxjs

import { startWith, tap, delay } from 'rxjs/operators';

// Data field used to populate on the html
dataSource: any;

....

ngAfterViewInit() {
  this.yourAsyncData.
      .pipe(
          startWith(null),
          delay(0),
          tap((res) => this.dataSource = res)
      ).subscribe();
}

¿Cuál fue el código problemático? ¿Cuál es la solución aquí?
mkb

Hola @mkb, el problema ocurrió ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.cuando los cambios de valor se activan cuando cambia el DOM
Sandeep K Nair

Hola, quiero decir, ¿qué hiciste aquí para superar el problema? ¿No usaste rxjs antes o agregaste delay () o agregaste startWith ()? Ya utilizo rxjs con varios métodos de rxjs pero aún obtengo el error, espero resolver el misterio :(
mkb

El agregado delayhace que el error desaparezca. Funciona de manera similar a setTimeout.
Lazar Ljubenović

1

Tuve este tipo de error en Ionic3 (que usa Angular 4 como parte de su pila de tecnología).

Para mí estaba haciendo esto:

<ion-icon [name]="getFavIconName()"></ion-icon>

Así que estaba tratando de cambiar condicionalmente el tipo de un ícono iónico de a pina a remove-circle, según el modo en que funcionaba una pantalla.

Supongo que tendré que agregar un *ngIfen su lugar.


1

Mi problema fue manifiesto cuando agregué *ngIfpero esa no fue la causa. El error fue causado al cambiar el modelo en las {{}}etiquetas y luego tratar de mostrar el modelo modificado en la *ngIfdeclaración posterior. Aquí hay un ejemplo:

<div>{{changeMyModelValue()}}</div> <!--don't do this!  or you could get error: ExpressionChangedAfterItHasBeenCheckedError-->
....
<div *ngIf="true">{{myModel.value}}</div>

Para solucionar el problema, cambié donde llamé changeMyModelValue()a un lugar que tenía más sentido.

En mi situación, quería que me changeMyModelValue()llamaran cada vez que un componente secundario cambiaba los datos. Esto requirió que creara y emitiera un evento en el componente hijo para que el padre pudiera manejarlo (llamando changeMyModelValue(). Ver https://angular.io/guide/component-interaction#parent-listens-for-child-event


0

Espero que esto ayude a alguien que viene aquí: hacemos llamadas de servicio ngOnInitde la siguiente manera y usamos una variabledisplayMain para controlar el Montaje de los elementos en el DOM.

componente.ts

  displayMain: boolean;
  ngOnInit() {
    this.displayMain = false;
    // Service Calls go here
    // Service Call 1
    // Service Call 2
    // ...
    this.displayMain = true;
  }

y component.html

<div *ngIf="displayMain"> <!-- This is the Root Element -->
 <!-- All the HTML Goes here -->
</div>

0

Recibí este error porque estaba usando una variable en component.html que no fue declarada en component.ts. Una vez que eliminé la parte en HTML, este error desapareció.


0

Recibí este error porque estaba enviando acciones redux en modal y modal no estaba abierto en ese momento. Estaba enviando acciones en el momento en que el componente modal recibe la entrada. Así que puse setTimeout allí para asegurarme de que modal está abierto y luego las acciones están dipatched.


0

Para cualquiera que esté luchando con esto. Aquí hay una manera de depurar correctamente este error: https://blog.angular-university.io/angular-debugging/

En mi caso, de hecho me libré de este error usando este truco [oculto] en lugar de * ngSi ...

Pero el enlace que proporcioné me permitió encontrar EL CULPABLE * ngIf :)

Disfrutar.


Usar en hiddenlugar de ngIfno es un truco, ni aborda el núcleo del problema en absoluto. Solo estás ocultando el problema.
Lazar Ljubenović

-2

La solución ... los servicios y los rxjs ... los emisores de eventos y el enlace de propiedad usan rxjs ... es mejor implementarlo usted mismo, más control, más fácil de depurar. Recuerde que los emisores de eventos están utilizando rxjs. Simplemente, cree un servicio y dentro de un observable, haga que cada componente se suscriba al observador y pase un nuevo valor o un valor de costo según sea necesario


1
No solo esto no responde la pregunta, también es un consejo terrible. Chicos, por favor, no vuelvan a implementar rxjs solo porque están recibiendo errores de CD de Angular. :)
Lazar Ljubenović
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.