Manuelles Auslösen der Änderungserkennung in Angular

387

Ich schreibe eine Angular-Komponente, die eine Eigenschaft hat Mode(): string.

Ich möchte in der Lage sein, diese Eigenschaft programmgesteuert und nicht als Reaktion auf ein Ereignis festzulegen.

Das Problem ist, dass eine Vorlagenbindung ohne Browserereignis {{Mode}}nicht aktualisiert wird.

Gibt es eine Möglichkeit, diese Änderungserkennung manuell auszulösen?

jz87
quelle

Antworten:

640

Probieren Sie eines davon aus:

  • ApplicationRef.tick()- ähnlich wie bei AngularJS $rootScope.$digest()- dh überprüfen Sie den vollständigen Komponentenbaum
  • NgZone.run(callback)- ähnlich wie $rootScope.$apply(callback)- dh die Rückruffunktion innerhalb der Winkelzone auswerten. Ich denke, aber ich bin nicht sicher, ob dies dazu führt, dass der vollständige Komponentenbaum nach dem Ausführen der Rückruffunktion überprüft wird.
  • ChangeDetectorRef.detectChanges()- ähnlich wie $scope.$digest()- dh nur diese Komponente und ihre untergeordneten Komponenten überprüfen

Sie können injizieren ApplicationRef, NgZoneoder ChangeDetectorRefin Ihrer Komponente.

Mark Rajcok
quelle
1
Vielen Dank, ich habe mich für die 3. Lösung entschieden, um nicht alles zu überprüfen, da die Änderungen ziemlich lokalisiert sind. Ich sollte die anderen Optionen untersuchen, wenn ich mehr Zeit habe. Gibt es bei jeder Auswahl Auswirkungen auf die Leistung?
jz87
36
+1 für ChangeDetectorRef.detectChanges(). Validatoren wurden ausgelöst, bevor meine Direktive den Wert einer Eingabe aktualisieren konnte.
ps2goat
7
ApplicationRef.tick () und ChangeDetectorRef.detectChanges () sind in final 2.0.0 noch vorhanden.
Max Mumford
51
Ich dachte nur, ich würde das erwähnen. Dies sind keine statischen Methoden, sondern Instanzmethoden. Sie müssen diese Klassen als Dienste einfügen.
Stephen Paul
1
ApplicationRef.tick () half bei der Lösung eines Problems mit FireFox v17 (<20)
Dan J
123

Ich habe eine akzeptierte Antwortreferenz verwendet und möchte ein Beispiel anführen, da die Angular 2-Dokumentation sehr schwer zu lesen ist. Ich hoffe, dass dies einfacher ist:

  1. Import NgZone:

    import { Component, NgZone } from '@angular/core';
    
  2. Fügen Sie es Ihrem Klassenkonstruktor hinzu

    constructor(public zone: NgZone, ...args){}
    
  3. Führen Sie den Code aus mit zone.run:

    this.zone.run(() => this.donations = donations)
    
Websites
quelle
6
Wo solltest du den zone.runCode platzieren und was genau ist donations?
Suku
@suku Spenden sind alle Objekte, die Sie aktualisieren möchten. Es könnte sich also um this.foo = bar handeln. zone.run geht dorthin, wo Sie etwas aktualisieren möchten.
Matthew Optional Meehan
4
Ich habe diese Lösung verwendet, um eine Ansichtsaktualisierung zu erzwingen, wenn document.addEventListener ("Lebenslauf", Rückruf) verwendet wird
marcovtwout
71

Ich konnte es mit markForCheck () aktualisieren

Importieren Sie ChangeDetectorRef

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

Injizieren und instanziieren

constructor(private ref: ChangeDetectorRef) { 
}

Zum Schluss soll die Änderungserkennung stattfinden

this.ref.markForCheck();

Hier ist ein Beispiel, in dem markForCheck () funktioniert und detectChanges () nicht.

https://plnkr.co/edit/RfJwHqEVJcMU9ku9XNE7?p=preview

BEARBEITEN: In diesem Beispiel wird das Problem nicht mehr dargestellt :( Ich glaube, es wird möglicherweise eine neuere Angular-Version ausgeführt, in der es behoben ist.

(Drücken Sie STOP / RUN, um es erneut auszuführen.)

Nuno Tomas
quelle
Goo-Punkt für DetectChanges () funktioniert nicht. Ich hatte das gleiche Problem festgestellt und festgestellt, dass es funktioniert, wenn die Änderungserkennung kein OnPush ist. Wäre gut, eine Erklärung dafür zu bekommen ...
Christian
2
Es scheint, als ob detectChanges tatsächlich in diesem Plunker funktioniert? Vermisse ich etwas
Jared_C
1
Sie sollten beachten, dass ChangeDetectorRef nur in Komponenten funktioniert
Kevinius
(!) Dies ist ein schlechtes Beispiel, es tut mir leid. Beispiel zeigt nichts. Der erste Artikel wird einfach überschrieben.
Passen Sie
Dieses Beispiel zeigt das Problem nicht mehr :( Ich glaube, es läuft möglicherweise eine neuere Angular-Version, in der es behoben ist.
Nuno Tomas
7

Probieren Sie in Angular 2+ den @ Input-Dekorator aus

Es ermöglicht eine nette Eigenschaftsbindung zwischen übergeordneten und untergeordneten Komponenten.

Erstellen Sie zunächst im übergeordneten Element eine globale Variable, die das Objekt / die Eigenschaft enthält, die an das untergeordnete Element übergeben werden.

Erstellen Sie als Nächstes eine globale Variable im untergeordneten Element, um das vom übergeordneten Objekt übergebene Objekt / die Eigenschaft zu speichern.

Fügen Sie dann im übergeordneten HTML-Code, in dem die untergeordnete Vorlage verwendet wird, eine eckige Klammer mit dem Namen der untergeordneten Variablen hinzu und setzen Sie sie gleich dem Namen der übergeordneten Variablen. Beispiel:

<child-component-template [childVariable] = parentVariable>
</child-component-template>

Fügen Sie schließlich, wo die untergeordnete Eigenschaft in der untergeordneten Komponente definiert ist, den Eingabe-Dekorator hinzu:

@Input()
public childVariable: any

Wenn Ihre übergeordnete Variable aktualisiert wird, sollte sie die Aktualisierungen an die untergeordnete Komponente übergeben, die ihr HTML aktualisiert.

Um eine Funktion in der untergeordneten Komponente auszulösen, werfen Sie einen Blick auf ngOnChanges.

Jeremy Swagger
quelle
2
NEIN ... das ist das Problem ... wenn Sie im übergeordneten Element aktualisieren ... sagen wir, dass das Beispiel "durch Referenz" in einer statischen Methode aktualisiert wird, wird das Kind es nicht aufheben, da
keine
Ich habe seit Tagen das gleiche Problem. Ich versuche, Daten aus dem PHP-Backend abzurufen, und die Daten werden überhaupt nicht aktualisiert. Unter Microsoft Edge funktioniert dies einwandfrei, bei anderen Browsern jedoch nicht. Ich bekomme immer die Daten, die ich zum ersten Mal bekommen habe, aber wenn sich Daten ändern, werden sie nicht in der Ansicht aktualisiert
el6976
1

ChangeDetectorRef.detectChanges () - ähnlich wie $ scope. $ Digest () - dh nur diese Komponente und ihre untergeordneten Komponenten überprüfen

Chetann
quelle