detectChanges() : void
Vérifie le détecteur de changement et ses enfants.
En d'autres termes, si un élément de votre modèle (votre classe) a été modifié mais n'a pas été répercuté sur la vue, vous devrez peut-être demander à Angular de détecter ces modifications (détection des modifications locales) et de mettre à jour la vue.
Les scénarios possibles pourraient être :
1- Le détecteur de changement est détaché de la vue ( voir détacher )
2- Une mise à jour a eu lieu mais elle n'est pas entrée dans la zone Angular, donc Angular n'est pas au courant.
Par exemple, lorsqu'une fonction tierce a mis à jour votre modèle et que vous souhaitez ensuite mettre à jour la vue.
someFunctionThatIsRunByAThirdPartyCode(){
yourModel.text = "new text";
}
Parce que ce code est en dehors de la zone d'Angular (probablement), vous devez très probablement vous assurer de détecter les changements et de mettre à jour la vue, ainsi :
myFunction(){
someFunctionThatIsRunByAThirdPartyCode();
// Let's detect the changes that above function made to the model which Angular is not aware of.
this.cd.detectChanges();
}
NOTE :
Il existe d'autres moyens de faire fonctionner ce qui précède, en d'autres termes, il existe d'autres moyens d'apporter ce changement dans le cycle de changement d'Angular.
** Vous pourriez envelopper cette fonction tierce dans une zone.run :
myFunction(){
this.zone.run(this.someFunctionThatIsRunByAThirdPartyCode);
}
** Vous pourriez envelopper la fonction dans un setTimeout :
myFunction(){
setTimeout(this.someFunctionThatIsRunByAThirdPartyCode,0);
}
3- Il y a aussi des cas où vous mettez à jour le modèle après le change detection cycle
est terminée, où dans ces cas vous obtenez cette redoutable erreur :
"L'expression a changé après avoir été vérifiée" ;
Cela signifie généralement (dans le langage Angular2) :
J'ai vu un changement dans votre modèle qui a été causé par l'une de mes méthodes acceptées ( événements, requêtes XHR, setTimeout, et ... ) et puis j'ai lancé ma détection de changement pour mettre à jour votre vue et je l'ai terminé, mais ensuite il y avait une autre fonction dans votre code qui a mis à jour le modèle à nouveau et je ne veux pas lancer ma détection de changement à nouveau parce qu'il n'y a pas de vérification sale comme AngularJS plus :D et nous devrions utiliser un flux de données à sens unique !
Vous rencontrerez certainement cette erreur :P .
Il y a plusieurs façons d'y remédier :
1- La bonne méthode : assurez-vous que la mise à jour se situe dans le cycle de détection des changements (les mises à jour d'Angular2 sont des flux à sens unique qui se produisent une fois, ne mettez pas à jour le modèle après cela et déplacez votre code à un meilleur endroit/temps).
2- La voie de la paresse : exécuter detectChanges() après cette mise à jour pour rendre angular2 heureux, ce n'est certainement pas la meilleure façon, mais comme vous avez demandé quels sont les scénarios possibles, c'en est un.
De cette façon, vous dites : je sais sincèrement que vous avez lancé la détection des changements, mais je veux que vous la refassiez parce que j'ai dû mettre à jour quelque chose à la volée après que vous ayez terminé la vérification.
3- Placez le code à l'intérieur d'un setTimeout
parce que setTimeout
est patché par zone et fonctionnera detectChanges
après qu'il soit terminé.
Extrait de la documentation
markForCheck() : void
Marque tous les ancêtres de ChangeDetectionStrategy comme devant être vérifiés.
Ceci est surtout nécessaire lorsque le ChangeDetectionStrategy de votre composant est OnPush .
OnPush signifie que la détection des changements ne doit être exécutée que si l'une de ces conditions est remplie :
1- L'une des @inputs du composant a été complètement remplacée par une nouvelle valeur, ou plus simplement, si la référence de la propriété @Input a changé du tout au tout.
Donc si ChangeDetectionStrategy de votre composant est OnPush et ensuite vous avez :
var obj = {
name:'Milad'
};
Et ensuite vous le mettez à jour/mutant comme :
obj.name = "a new name";
Cela ne mettra pas à jour le obj. La détection de changement ne sera donc pas exécutée, et la vue ne reflète pas la mise à jour/mutation.
Dans ce cas, vous devez indiquer manuellement à Angular de vérifier et de mettre à jour la vue (markForCheck) ;
Donc si tu as fait ça :
obj.name = "a new name";
Vous devez le faire :
this.cd.markForCheck();
Plutôt, ci-dessous, cela provoquerait l'exécution d'une détection de changement :
obj = {
name:"a new name"
};
qui a complètement remplacé l'objet précédent par un nouvel objet {}
;
2- Un événement a été déclenché, comme un clic ou quelque chose comme ça, ou l'un des composants enfants a émis un événement.
Des événements tels que :
- Cliquez sur
- Keyup
- Événements d'abonnement
- etc.
En résumé :
-
Utilisez detectChanges()
lorsque vous avez mis à jour le modèle après qu'angular ait lancé sa détection de changement, ou si la mise à jour n'a pas été dans le monde angulaire du tout.
-
Utilisez markForCheck()
si vous utilisez OnPush et que vous contournez l'option ChangeDetectionStrategy
en mutant certaines données ou vous avez mis à jour le modèle dans une setTimeout ;