web-dev-qa-db-fra.com

Comment déclencher un événement de modification manuellement - angular2

É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

18
suat

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.

Détection manuelle des modifications

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:

15
Maxim Koretskyi

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;
}
0
Behzad Jafari