ExpressionChangedAfterItHasBeenCheckedError expliqué

308

Veuillez m'expliquer pourquoi je continue à recevoir cette erreur: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.

Évidemment, je ne l'obtiens qu'en mode dev, cela ne se produit pas sur ma version de production, mais c'est très ennuyeux et je ne comprends tout simplement pas les avantages d'avoir une erreur dans mon environnement de développement qui n'apparaîtra pas sur prod - -probablement à cause de mon manque de compréhension.

Habituellement, le correctif est assez facile, j'encapsule simplement l'erreur provoquant le code dans un setTimeout comme ceci:

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

Ou forcez la détection des modifications avec un constructeur comme celui-ci constructor(private cd: ChangeDetectorRef) {}:

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

Mais pourquoi est-ce que je rencontre constamment cette erreur? Je veux le comprendre afin que je puisse éviter ces corrections hacky à l'avenir.

Kevin LeStarge
la source

Réponses:

121

J'ai eu un problème similaire. En regardant la documentation des hooks du cycle de vie , j'ai changé ngAfterViewInitpour ngAfterContentInitet cela a fonctionné.

seulement moi
la source
@PhilipEnc mon problème était lié à une modification déclenchée par la modification du DOM. Lorsque le DOM change, l'objet QueryList (qui provient d'une propriété @ContentChildren) est mis à jour et, à l'intérieur de la méthode que la mise à jour l'appelle, change la propriété liée dans les deux sens. Cela a créé le problème que j'avais. Envelopper ce changement dans les deux propriétés avec setTimeoutcomme vous le montre ci-dessus a fait l'affaire. Merci!
kbpontius
1
Dans mon cas, j'avais placé du code qui a changé la valeur du tableau de grille primeng dans ngAfterContentInit, j'ai placé le code dans ngOnInit et cela a fonctionné.
Vibhu
ngAfterContentCheckedfonctionne ici tout ngAfterContentIniten lançant toujours une erreur.
ashubuntu
ngAfterContentChecked utilisation mais projet chargé très lentement
Ghotekar Rahul
101

Cette erreur indique un problème réel dans votre application, il est donc judicieux de lever une exception.

Dans la devModedétection de changement, un tour supplémentaire est ajouté après chaque exécution régulière de détection de changement pour vérifier si le modèle a changé.

Si le modèle a changé entre le tour de détection de changement régulier et le changement supplémentaire, cela indique que

  • la détection des changements elle-même a provoqué un changement
  • une méthode ou un getter renvoie une valeur différente à chaque appel

qui sont tous les deux mauvais, car il n'est pas clair comment procéder car le modèle pourrait ne jamais se stabiliser.

Si les exécutions angulaires changent de détection jusqu'à ce que le modèle se stabilise, il peut s'exécuter indéfiniment. Si Angular n'exécute pas la détection des modifications, la vue peut ne pas refléter l'état actuel du modèle.

Voir également Quelle est la différence entre le mode de production et le mode de développement dans Angular2?

Günter Zöchbauer
la source
4
Comment puis-je éviter de voir cette erreur à l'avenir? Existe-t-il une manière différente de penser à mon code pour m'assurer que je ne fais pas les mêmes erreurs?
Kevin LeStarge
25
Habituellement, cela est causé par certains rappels de cycle de vie comme ngOnInitou ngOnChangespour modifier le modèle (certains rappels de cycle de vie permettent de modifier le modèle, d'autres non, je ne me souviens pas exactement de ce que l'on fait ou ne fait pas). Ne vous liez pas aux méthodes ou aux fonctions de la vue, mais liez-les aux champs et mettez à jour les champs dans les gestionnaires d'événements. Si vous devez vous lier à des méthodes, assurez-vous qu'elles renvoient toujours la même instance de valeur tant qu'il n'y a pas eu réellement de changement. La détection des changements appellera beaucoup ces méthodes.
Günter Zöchbauer
Pour toute personne arrivant ici qui obtient cette erreur en utilisant la bibliothèque ngx-toaster, voici le rapport de bogue: github.com/scttcper/ngx-toastr/issues/160
rmcsharry
2
Ce n'est pas nécessairement un problème avec l'application. Le fait que l'appel changeRef.detectChanges()soit une solution / supprime l'erreur en est la preuve. C'est comme modifier l'état à l'intérieur $scope.$watch()d'Angular 1.
Kevin Beal
1
Je ne connais pas trop Angular 1 mais la détection de changement dans Angular 2 fonctionne très différemment. Vous avez raison de dire que ce n'est pas nécessairement un problème, mais qu'il cdRef.detectChanges()n'est généralement nécessaire que dans certains cas étranges et vous devez regarder attentivement lorsque vous en avez besoin et comprendre pourquoi.
Günter Zöchbauer
83

Beaucoup de compréhension est venue une fois que j'ai compris les crochets de cycle de vie angulaire et leur relation avec la détection des changements.

J'essayais d'obtenir Angular pour mettre à jour un indicateur global lié à l' *ngIfélément, et j'essayais de changer cet indicateur à l'intérieur du ngOnInit()crochet de cycle de vie d'un autre composant.

Selon la documentation, cette méthode est appelée après que Angular a déjà détecté des modifications:

Appelé une fois, après le premier ngOnChanges ().

La mise à jour du drapeau à l'intérieur de ngOnChanges()n'initiera donc pas la détection des modifications. Ensuite, une fois que la détection des modifications s'est à nouveau naturellement déclenchée, la valeur de l'indicateur a changé et l'erreur est levée.

Dans mon cas, j'ai changé cela:

constructor(private globalEventsService: GlobalEventsService) {

}

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

Pour ça:

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

ngOnInit() {

}

et cela a résolu le problème :)

Kevin LeStarge
la source
3
Mon problème était similaire. Que j'ai fait une erreur après de longues heures et défini une variable en dehors de la fonction et du constructeur ngOnInit. Celui-ci reçoit les changements de données d'un observable, qui est placé dans la fonction d'initalisation. A fait la même chose que vous pour corriger l'erreur.
ravo10
1
Très similaire tout autour, mais j'essayais de faire défiler ( router.navigate) lors du chargement vers un fragment s'il était présent dans l'URL. Ce code a été initialement placé AfterViewInitlà où je recevais l'erreur, puis j'ai déménagé comme vous le dites au constructeur mais il ne respectait pas le fragment. Déplacement vers ngOnInitrésolu :) merci!
Joel Balmer
Que faire si mon html est lié à un getter renvoyant l'heure en tant que "HH: MM" via get ClockValue () {return DateTime.TimeAMPM (new Date ())} il finira par se déclencher lorsque les minutes changeront pendant la détection, comment puis-je répare ça?
Meryan
Pareil ici. A également constaté que l'habillage setInterval()fonctionne également s'il doit se déclencher après un autre code d'événement à vie.
Rick Strahl
39

Mettre à jour

Je recommande fortement de commencer par l'auto-réponse du PO : réfléchissez correctement à ce qui peut être fait dans le constructorvs ce qui devrait être fait dans ngOnChanges().

Original

C'est plus une note que une réponse, mais cela pourrait aider quelqu'un. Je suis tombé sur ce problème en essayant de faire dépendre la présence d'un bouton de l'état du formulaire:

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

Pour autant que je sache, cette syntaxe entraîne l'ajout et la suppression du bouton du DOM en fonction de la condition. Qui à son tour conduit à la ExpressionChangedAfterItHasBeenCheckedError.

La solution dans mon cas (bien que je ne prétende pas saisir toutes les implications de la différence), était d'utiliser à la display: noneplace:

<button [style.display]="form.pristine ? 'inline' : 'none'">Yo</button>
Arnaud P
la source
6
Ma compréhension de la différence entre le ngIf et le style est que le ngIf n'inclut pas le HTML dans la page jusqu'à ce que la condition soit vraie, réduisant ainsi le "poids de la page" un tout petit peu tandis que la technique de style fait que le HTML soit toujours dans la page et est simplement masqué ou affiché en fonction de la valeur de form.pristine.
user3785010
4
Vous pourriez aussi bien utiliser à la [hidden]place de la [style.display]partie très verbeuse . :)
Philipp Meissner
2
Pourquoi pas. Bien que, comme mentionné par @Simon_Weaver dans un autre commentaire sur cette page, il [hidden] n'aura pas toujours le même comportement quedisplay: none
Arnaud P
1
Je montrais deux boutons différents (déconnexion / connexion) avec * ngIf dans chaque bouton et cela causait le problème.
GoTo
constructeur était le bon endroit pour moi, lançant un snack-bar matériel
austin
31

Il y avait des réponses intéressantes mais je ne semblais pas en trouver une qui correspondait à mes besoins, la plus proche étant de @ chittrang-mishra qui ne fait référence qu'à une fonction spécifique et non à plusieurs bascules comme dans mon application.

Je ne voulais pas utiliser [hidden]pour profiter de *ngIfne même pas faire partie du DOM, j'ai donc trouvé la solution suivante qui n'est peut-être pas la meilleure pour tous car elle supprime l'erreur au lieu de la corriger, mais dans mon cas où je connais le le résultat final est correct, cela semble correct pour mon application.

Ce que j'ai fait, c'est mettre en œuvre AfterViewChecked, ajouter constructor(private changeDetector : ChangeDetectorRef ) {}, puis

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

J'espère que cela aide les autres comme beaucoup d'autres m'ont aidé.

eper
la source
3
cela ne déclenchera-t-il pas une boucle de détection de changement infini? je veux dire, vous détectez des changements après avoir vérifié.
Manuel Azar
@ManuelAzar Apparemment non. C'est la SEULE solution qui a fonctionné pour moi. Enfin un peu de silence dans ma console. J'étais tellement fatigué de toutes ces "erreurs" de détection de changement non pertinentes.
Jeremy Thille
31

Angular exécute la détection de changement et lorsqu'il détecte que certaines valeurs qui ont été transmises au composant enfant ont été modifiées, Angular renvoie l'erreur:

ExpressionChangedAfterItHasBeenCheckedError cliquez pour en savoir plus

Pour corriger cela, nous pouvons utiliser le AfterContentCheckedcrochet de cycle de vie et

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

  constructor(
  private cdref: ChangeDetectorRef) { }

  ngAfterContentChecked() {

    this.cdref.detectChanges();

  }
Lijo
la source
Bien que cela puisse résoudre le problème, n'est-ce pas très cher et surcharger le CD?
Nicky
Je pense que c'est la seule réponse qui résout cette erreur causée par la transmission de valeurs à un enfant. Merci!
java-addict301
@ Nicky Oui. Chaque fois que vous touchez l'écran, n'importe où, ngAfterContentChecked () est appelé
Mert Mertce
25

Dans mon cas, j'ai eu ce problème dans mon fichier de spécifications, lors de l'exécution de mes tests.

Je devais changer ngIf pour [hidden]

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

à

<app-loading [hidden]="!isLoading"></app-loading>
Andre Evangelista
la source
1
À propos de [hidden]: speakdotnet.com/dont-use-hidden-attribute-angularjs-2
Simon_Weaver
2
La différence ici est que cela *ngIfchange le DOM, en ajoutant et en supprimant l'élément de la page, tout en [hidden]changeant la visibilité de l'élément sans le supprimer du DOM.
Grungondola
5
Mais cela n'a pas vraiment résolu le vrai problème ...?
ravo10
23

Suivez les étapes ci-dessous:

1. Utilisez «ChangeDetectorRef» en l'important de @ angular / core comme suit:

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

2. Implémentez-le dans constructor () comme suit:

constructor(   private cdRef : ChangeDetectorRef  ) {}

3. Ajoutez la méthode suivante à votre fonction que vous appelez lors d'un événement comme un clic sur le bouton. Cela ressemble donc à ceci:

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

J'utilisais ng2-carouselamos (Angular 8 & Bootstrap 4)

Ci-dessous résolu mon problème:

Ce que j'ai fait:

1. implement AfterViewChecked,  
2. add constructor(private changeDetector : ChangeDetectorRef ) {} and then 
3. ngAfterViewChecked(){ this.changeDetector.detectChanges(); }
Shahid Hussain Abbasi
la source
Ça m'a aidé. Incroyable!!
Pathik Vejani
Vous m'avez sauvé la journée ... Merci!
omostan
19

J'étais confronté au même problème que la valeur changeait dans l'un des tableaux de mon composant. Mais au lieu de détecter les changements lors du changement de valeur, j'ai changé la stratégie de détection de changement de composant en onPush(qui détectera les changements lors du changement d'objet et non lors du changement de valeur).

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

@Component({
    changeDetection: ChangeDetectionStrategy.OnPush
    selector: -
    ......
})
Dheeraj
la source
Cela a semblé fonctionner pour ajouter / supprimer des contrôles dynamiquement .. y a-t-il des inconvénients?
Ricardo Saracino
Fonctionne comme un charme dans la situation que j'ai sous la main, merci! Un composant était lié à un objet "global" qui a été modifié ailleurs et a provoqué l'erreur. Ce composant avait déjà un gestionnaire de mise à jour pour quand l'objet lié a été mis à jour, ce gestionnaire d'événements appelle désormais changeDetectorRef.detectChanges () en combinaison avec ChangeDetectionStrategy.OnPush, cela fonctionne comme vous le souhaitez sans l'erreur.
Bernoulli IT
@RicardoSaracino avez-vous trouvé des inconvénients? Je me demandais la même chose. Je sais comment fonctionne la détection de changement OnPush, mais je me demande s'il y a un problème que je manque peut-être. Je ne veux pas avoir à revenir en arrière.
mtpultz
@RicardoSaracino, Oui, il a quelques inconvénients, vous pouvez consulter ce lien détaillé blog.angular-university.io/onpush-change-detection-how-it-works
Dheeraj
@BernoulliIT Merci, je suis heureux que cela ait fonctionné pour vous.
Dheeraj
17

Se référant à l'article https://blog.angularindepth.com/everything-you-need-to-know-about-the-expressionchangedafterithasbeencheckederror-error-e3fd9ce7dbb4

Ainsi, la mécanique derrière la détection des modifications fonctionne en fait de manière à ce que les analyses de détection des modifications et de vérification soient effectuées de manière synchrone. Cela signifie que si nous mettons à jour les propriétés de manière asynchrone, les valeurs ne seront pas mises à jour lorsque la boucle de vérification est en cours d'exécution et nous n'obtiendrons pas d' ExpressionChanged...erreur. La raison pour laquelle nous obtenons cette erreur est que, pendant le processus de vérification, Angular voit différentes valeurs, puis ce qu'il a enregistré pendant la phase de détection de changement. Donc, pour éviter cela ...

1) Utilisez changeDetectorRef

2) utilisez setTimeOut. Cela exécutera votre code dans une autre machine virtuelle en tant que macro-tâche. Angular ne verra pas ces changements pendant le processus de vérification et vous n'obtiendrez pas cette erreur.

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

3) Si vous voulez vraiment exécuter votre code sur la même machine virtuelle, utilisez

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

Cela créera une micro-tâche. La file d'attente des microtâches est traitée une fois que le code synchrone en cours a terminé son exécution, la mise à jour de la propriété aura donc lieu après l'étape de vérification.

ATHER
la source
Pouvez-vous utiliser l'option # 3 avec une expression de style? J'ai une expression de style pour la hauteur qui doit être évaluée en dernier, car elle est basée sur le contenu injecté.
N-ate
1
Désolé, je viens de voir votre commentaire, oui, je ne vois aucune raison de ne pas le faire. Cela devrait donc également fonctionner avec les changements de style.
ATHER
4

@HostBinding peut être une source déroutante de cette erreur.

Par exemple, supposons que vous ayez la liaison hôte suivante dans un composant

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

Pour simplifier, supposons que cette propriété est mise à jour via la propriété d'entrée suivante:

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

Dans le composant parent, vous le définissez par programme dans ngAfterViewInit

@ViewChild(ImageCarousel) carousel: ImageCarousel;

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

Voici ce qui se passe:

  • Votre composant parent est créé
  • Le composant ImageCarousel est créé et affecté à carousel(via ViewChild)
  • Nous ne pouvons pas accéder carouseljusqu'à ngAfterViewInit()(ce sera nul)
  • Nous attribuons la configuration, qui définit style_groupBG = 'red'
  • Ceci à son tour définit background: redle composant ImageCarousel hôte
  • Ce composant est «détenu» par votre composant parent, donc quand il vérifie les changements, il trouve un changement carousel.style.backgroundet n'est pas assez intelligent pour savoir que ce n'est pas un problème, donc il lève l'exception.

Une solution consiste à introduire un autre diviseur de wrapper ImageCarousel et à définir la couleur d'arrière-plan, mais vous n'obtenez pas certains des avantages de l'utilisation HostBinding (comme permettre au parent de contrôler les limites complètes de l'objet).

La meilleure solution, dans le composant parent, consiste à ajouter detectChanges () après avoir défini la configuration.

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

Cela peut sembler assez évident comme ceci, et très similaire à d'autres réponses, mais il y a une différence subtile.

Considérez le cas où vous n'ajoutez @HostBindingque plus tard au cours du développement. Soudain, vous obtenez cette erreur et cela ne semble pas avoir de sens.

Simon_Weaver
la source
2

Voici mes réflexions sur ce qui se passe. Je n'ai pas lu la documentation mais je suis sûr que cela fait partie des raisons pour lesquelles l'erreur est affichée.

*ngIf="isProcessing()" 

Lorsque vous utilisez * ngIf, il modifie physiquement le DOM en ajoutant ou supprimant l'élément à chaque fois que la condition change. Donc, si la condition change avant d'être rendue à la vue (ce qui est hautement possible dans le monde d'Angular), l'erreur est levée. Voir l'explication ici entre les modes de développement et de production.

[hidden]="isProcessing()"

Lors de son utilisation, [hidden]il ne modifie pas physiquement le, DOMmais le cache simplement elementà la vue, probablement CSSà l'arrière. L'élément est toujours là dans le DOM mais n'est pas visible selon la valeur de la condition. C'est pourquoi l'erreur ne se produira pas lors de l'utilisation [hidden].

Kobus
la source
Si isProcessing()fait la chose ame, vous devez utiliser !isProcessing()pour le[hidden]
Matthieu Charbonnier
hiddenne "utilise pas CSS à l'arrière", c'est une propriété HTML standard. developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/…
Lazar Ljubenović
1

Pour mon problème, je lisais github - "ExpressionChangedAfterItHasBeenCheckedError lors de la modification de la valeur" non modèle "d'un composant dans afterViewInit" et j'ai décidé d'ajouter le ngModel

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

Cela a résolu mon problème, j'espère que cela aide quelqu'un.

Demodave
la source
1
Où sur ce site dit-il d'ajouter ngModel. Et pourriez-vous expliquer pourquoi cela devrait être utile?
Peter Wippermann
Lorsque je traquais ce problème, cela m'a amené à enquêter sur le lien. Après avoir lu l'article, j'ai ajouté l'attribut et cela a résolu mon problème. Il est utile que quelqu'un rencontre le même problème.
Demodave
1

Conseils de débogage

Cette erreur peut être assez déroutante, et il est facile de faire une hypothèse erronée sur exactement quand elle se produit. Je trouve utile d'ajouter de nombreuses instructions de débogage comme celle-ci dans les composants concernés aux endroits appropriés. Cela aide à comprendre le flux.

Dans le parent, mettez des instructions comme celle-ci (la chaîne exacte 'EXPRESSIONCHANGED' est importante), mais à part cela, ce ne sont que des exemples:

    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');

Dans les rappels enfant / services / timer:

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

Si vous exécutez detectChangesmanuellement ajouter la journalisation pour cela aussi:

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

Ensuite, dans le débogueur Chrome, filtrez simplement par "EXPRESSIONCHANGES". Cela vous montrera exactement le flux et l'ordre de tout ce qui est réglé, et aussi exactement à quel point Angular jette l'erreur.

entrez la description de l'image ici

Vous pouvez également cliquer sur les liens gris pour insérer des points d'arrêt.

Une autre chose à surveiller si vous avez des propriétés de nom similaire dans votre application (comme style.background) assurez-vous de déboguer celle que vous pensez - en la définissant sur une valeur de couleur obscure.

Simon_Weaver
la source
1

Dans mon cas, j'avais une propriété asynchrone LoadingServiceavec un BehavioralSubjectisLoading

L'utilisation du modèle [caché] fonctionne, mais * ngIf échoue

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

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

Une solution qui a fonctionné pour moi en utilisant 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();
}
Sandeep K Nair
la source
quel était le code problématique? quelle est la solution ici?
mkb
Salut @mkb, le problème s'est produit ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.lorsque des changements de valeur sont déclenchés lorsque le DOM change
Sandeep K Nair
Salut, je veux dire qu'avez-vous fait ici pour surmonter le problème. Vous n'avez pas utilisé rxjs avant ou ajouté delay (), ou ajouté startWith ()? J'utilise déjà rxjs avec diverses méthodes rxjs mais j'obtiens toujours l'erreur, j'espère résoudre le mystère :(
mkb
L'ajout fait delaydisparaître l'erreur. Cela fonctionne de manière similaire à setTimeout.
Lazar Ljubenović
1

J'ai eu ce genre d'erreur dans Ionic3 (qui utilise Angular 4 dans le cadre de sa pile technologique).

Pour moi, cela faisait ceci:

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

J'essayais donc de changer conditionnellement le type d'une icône ionique de a pinà a remove-circle, par un mode sur lequel un écran fonctionnait.

Je suppose que je vais devoir ajouter un à la *ngIfplace.

JGFMK
la source
1

Mon problème était manifeste lorsque j'ai ajouté *ngIfmais ce n'était pas la cause. L'erreur a été provoquée en modifiant le modèle dans les {{}}balises, puis en essayant d'afficher le modèle modifié dans l' *ngIfinstruction plus tard. Voici un exemple:

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

Pour résoudre le problème, j'ai changé l'endroit où j'ai appelé changeMyModelValue()vers un endroit qui avait plus de sens.

Dans ma situation, je voulais être changeMyModelValue()appelé chaque fois qu'un composant enfant modifiait les données. Cela nécessitait que je crée et émette un événement dans le composant enfant pour que le parent puisse le gérer (en appelant changeMyModelValue(). Voir https://angular.io/guide/component-interaction#parent-listens-for-child-event

goku_da_master
la source
0

J'espère que cela aide quelqu'un à venir ici: nous faisons des appels de service ngOnInitde la manière suivante et utilisons une variabledisplayMain pour contrôler le montage des éléments sur le DOM.

component.ts

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

et component.html

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

J'ai eu cette erreur car j'utilisais une variable dans component.html qui n'était pas déclarée dans component.ts. Une fois que j'ai supprimé la pièce en HTML, cette erreur a disparu.

shreekar hegde
la source
0

J'ai eu cette erreur car j'envoyais des actions redux en modal et le modal n'était pas ouvert à ce moment-là. Je distribuais des actions au moment où le composant modal recevait l'entrée. J'ai donc mis setTimeout là pour m'assurer que le modal est ouvert et que les actions sont déduites.

Muneem Habib
la source
0

À toute personne aux prises avec cela. Voici un moyen de déboguer correctement cette erreur: https://blog.angular-university.io/angular-debugging/

Dans mon cas, en effet, je me suis débarrassé de cette erreur en utilisant ce hack [caché] au lieu de * ngIf ...

Mais le lien que j'ai fourni m'a permis de trouver LA COUPABLE * ngIf :)

Prendre plaisir.

Deunz
la source
Utiliser hiddenau lieu de ngIfn'est pas un hack, ni ne résout le problème du tout. Vous masquez simplement le problème.
Lazar Ljubenović
-2

La solution ... les services et les émetteurs d'événements rxjs ... et la liaison de propriété utilisent tous deux rxjs..vous êtes mieux de l'implémenter vous-même, plus de contrôle, plus facile à déboguer. N'oubliez pas que les émetteurs d'événements utilisent rxjs. Simplement, créez un service et dans un observable, faites abonner chaque composant à l'observateur et passez une nouvelle valeur ou une valeur de cosume selon les besoins

user998548
la source
1
Non seulement cela ne répond pas à la question, mais c'est aussi un conseil terrible. Les gars, veuillez ne pas réimplémenter rxjs vous-même simplement parce que vous obtenez des erreurs de CD d'Angular. :)
Lazar Ljubenović