Étant donné les composants suivants:
@Component({
selector: 'compA',
template: template: `<compB [item]=item></compB>`
})
export class CompA {
item:any;
updateItem():void {
item[name] = "updated name";
}
}
@Component({
selector: 'compB',
template: template: `<p>{{item[name]}}</p>`
})
export class CompB implements OnInit{
@Input() item: any;
someArray: any[];
ngOnInit():void {
someArray.Push("something");
}
}
Pour autant que j'ai compris qu'à moins que l'objet item
complet ne soit changé, angular2 ne reconnaît pas les changements sur item
. Par conséquent, je voudrais émettre un événement de modification manuellement pour item
lorsque la méthode updateItem
est appelée. Et ensuite, faites en sorte que le composant enfant, c'est-à-dire CompB
, soit rendu de nouveau comme si angular a détecté un changement de manière régulière.
Actuellement, ce que j'ai fait est d'implémenter la méthode ngOnInit
de for CompB
et d'appeler cette méthode à l'intérieur de la méthode updateItem
via un lien ViewChild
. Une autre partie de l'histoire est que ma source actuelle a des objets comme someArray
que j'aimerais réinitialiser dans chaque rendu. Cependant, je ne suis pas sûr que le nouveau rendu réinitialise someArray
. Actuellement, je les réinitialise dans la méthode ngOnInit
.
Donc, ma question est: comment déclencher un nouveau rendu pour les modifications sur les éléments plus profonds d'un objet parent?
Merci
Pour autant que je sache, à moins que l'objet complet de l'élément ne soit modifié, angular2 ne reconnaît pas les modifications apportées à l'élément.
Ce n'est pas si simple. Vous devez faire la distinction entre le déclenchement de ngOnChanges
lorsque l'objet est muté et la mise à jour DOM du composant enfant. Angular ne reconnaît pas que item
est modifié et ne déclenche pas un hook de cycle de vie ngOnChanges
, mais le DOM sera toujours mis à jour si vous référencez une propriété particulière item
dans le modèle. C'est parce que la référence à l'objet est préservée. Par conséquent, pour avoir ce comportement:
Et après, faites le composant enfant, c'est-à-dire CompB, restitué comme si angular détecté un changement de la manière régulière.
Vous n'avez rien à faire en particulier car vous aurez toujours une mise à jour dans le DOM.
Vous pouvez insérer un détecteur de changement et le déclencher comme ceci:
@Component({
selector: 'compA',
template: template: `<compB [item]=item></compB>`
})
export class CompA {
item:any;
constructor(cd: ChangeDetectorRef) {}
updateItem():void {
item[name] = "updated name";
this.cd.detectChanges();
}
}
Cela déclenche la détection des modifications pour le composant actuel et tous ses enfants.
Mais cela n'aura aucun effet dans votre cas car même si Angular ne détecte pas de changement dans item
it exécute toujours la détection de changement pour le composant enfant B
et met à jour le DOM .
À moins que vous n'utilisiez ChangeDetectionStrategy.OnPush
. Dans ce cas, une façon de procéder serait de faire une vérification manuelle dans le crochet ngDoCheck
du CompB
:
import { ChangeDetectorRef } from '@angular/core';
export class CompB implements OnInit{
@Input() item: any;
someArray: any[];
previous;
constructor(cd: ChangeDetectorRef) {}
ngOnInit():void {
this.previous = this.item.name;
someArray.Push("something");
}
ngDoCheck() {
if (this.previous !== this.item.name) {
this.cd.detectChanges();
}
}
}
Vous pouvez trouver plus d'informations dans les articles suivants:
vous pouvez mettre une autre entrée dans CompB, donc quand vous voulez changer les propriétés d'un élément dans CompA, changez simplement la valeur de cette entrée.
@Component({
selector: 'compA',
template: template: `<compB [item]=item [trigger]=trigger></compB>`
})
export class CompA {
item:any;
trigger: any;
updateItem():void {
item[name] = "updated name";
trigger = new Object();
}
}
@Component({
selector: 'compB',
template: template: `<p>{{item[name]}}</p>`
})
export class CompB implements OnInit{
@Input() item: any;
@Input() trigger: any;
}