Ich habe eine übergeordnete Komponente ( CategoryComponent ), eine untergeordnete Komponente ( videoListComponent ) und einen ApiService.
Ich habe das meiste davon in Ordnung, dh jede Komponente kann auf die JSON-API zugreifen und ihre relevanten Daten über Observables abrufen.
Derzeit erhält die Videolistenkomponente nur alle Videos. Ich möchte dies nur nach Videos in einer bestimmten Kategorie filtern. Dies habe ich erreicht, indem ich die categoryId über an das Kind übergeben habe @Input()
.
CategoryComponent.html
<video-list *ngIf="category" [categoryId]="category.id"></video-list>
Dies funktioniert und wenn sich die übergeordnete CategoryComponent-Kategorie ändert, wird der categoryId-Wert über weitergeleitet, @Input()
aber ich muss dies in VideoListComponent erkennen und das Video-Array über APIService (mit der neuen categoryId) erneut anfordern.
In AngularJS hätte ich eine $watch
Variable erstellt. Was ist der beste Weg, um damit umzugehen?
quelle
Antworten:
Tatsächlich gibt es zwei Möglichkeiten, um zu erkennen und darauf zu reagieren, wenn sich eine Eingabe in der untergeordneten Komponente in angle2 + ändert:
Dokumentationslinks: ngOnChanges, SimpleChanges, SimpleChange
Demo Beispiel: Sehen Sie sich diesen Plunker an
Dokumentationslink: Schauen Sie hier .
Demo-Beispiel: Sehen Sie sich diesen Plunker an .
Welchen Ansatz sollten Sie verwenden?
Wenn Ihre Komponente mehrere Eingaben hat, erhalten Sie bei Verwendung von ngOnChanges () alle Änderungen für alle Eingaben gleichzeitig in ngOnChanges (). Mit diesem Ansatz können Sie auch aktuelle und vorherige Werte der geänderten Eingabe vergleichen und entsprechende Maßnahmen ergreifen.
Wenn Sie jedoch etwas tun möchten, wenn sich nur eine bestimmte Eingabe ändert (und Sie sich nicht um die anderen Eingaben kümmern), ist es möglicherweise einfacher, einen Eingabe-Eigenschaftssetzer zu verwenden. Dieser Ansatz bietet jedoch keine integrierte Möglichkeit, frühere und aktuelle Werte der geänderten Eingabe zu vergleichen (was mit der ngOnChanges-Lebenszyklusmethode problemlos möglich ist).
EDIT 2017-07-25: ANGULAR CHANGE DETECTION KANN UNTER EINIGEN UMSTÄNDEN NOCH NICHT FEUERN
Normalerweise wird die Änderungserkennung sowohl für Setter als auch für ngOnChanges ausgelöst, wenn die übergeordnete Komponente die Daten ändert, die an das untergeordnete Element übergeben werden, vorausgesetzt, die Daten sind ein primitiver JS-Datentyp (Zeichenfolge, Zahl, Boolescher Wert) . In den folgenden Szenarien wird es jedoch nicht ausgelöst und Sie müssen zusätzliche Maßnahmen ergreifen, damit es funktioniert.
Wenn Sie ein verschachteltes Objekt oder Array (anstelle eines primitiven JS-Datentyps) verwenden, um Daten von Parent zu Child zu übergeben, wird die Änderungserkennung (entweder mit Setter oder ngchanges) möglicherweise nicht ausgelöst, wie auch in der Antwort des Benutzers: muetzerich erwähnt. Lösungen finden Sie hier .
Wenn Sie Daten außerhalb des Winkelkontexts (dh extern) mutieren, kennt Angular die Änderungen nicht. Möglicherweise müssen Sie ChangeDetectorRef oder NgZone in Ihrer Komponente verwenden, um externe Änderungen im Winkel zu erkennen und damit die Änderungserkennung auszulösen. Beziehen Sie sich darauf .
quelle
doSomething
Methode aufrufen und 2 Argumente für die neuen und alten Werte verwenden, bevor Sie den neuen Wert auf eine andere Weise festlegen würde den alten Wert speichern, bevor die Methode danach gesetzt und aufgerufen wird.Verwenden Sie die
ngOnChanges()
Lebenszyklusmethode in Ihrer Komponente.Hier sind die Dokumente .
quelle
MyComponent.myArray = []
, aber wenn ein Eingabewert verändert zB istMyComponent.myArray.push(newValue)
,ngOnChanges()
wird nicht ausgelöst. Irgendwelche Ideen, wie diese Änderung erfasst werden kann?ngOnChanges()
wird nicht aufgerufen, wenn sich ein verschachteltes Objekt geändert hat. Vielleicht finden Sie eine Lösung hierBei der Verwendung des
SimpleChanges
Typs in der Funktionssignatur wurden Fehler in der Konsole sowie im Compiler und in der IDE angezeigt. Verwenden Sieany
stattdessen das Schlüsselwort in der Signatur, um Fehler zu vermeiden .BEARBEITEN:
Wie Jon weiter unten ausgeführt hat, können Sie die
SimpleChanges
Signatur verwenden, wenn Sie die Klammernotation anstelle der Punktnotation verwenden.quelle
SimpleChanges
Benutzeroberfläche oben in Ihrer Datei importiert ?<my-user-details [user]="selectedUser"></my-user-details>
) gebunden . Auf diese Eigenschaft wird von der SimpleChanges-Klasse durch Aufrufen zugegriffenchanges.user.currentValue
. Hinweisuser
ist zur Laufzeit gebunden und nicht Teil des SimpleChanges-ObjektsngOnChanges(changes: {[propName: string]: SimpleChange}) { console.log('onChanges - myProp = ' + changes['myProp'].currentValue); }
Am sichersten ist es, einen gemeinsamen Dienst anstelle eines
@Input
Parameters zu verwenden. Außerdem@Input
erkennt der Parameter keine Änderungen im komplexen verschachtelten Objekttyp.Ein einfacher Beispieldienst lautet wie folgt:
Sie können eine ähnliche Implementierung in anderen Komponenten verwenden, und alle Ihre Komponenten haben dieselben gemeinsamen Werte.
quelle
@Input
Parameter @JoshuaKemmerer erkennt keine Änderungen am komplexen verschachtelten Objekttyp, jedoch an einfachen nativen Objekten.Ich möchte nur hinzufügen, dass es einen weiteren Lifecycle-Hook
DoCheck
gibt, der nützlich ist, wenn der@Input
Wert kein primitiver Wert ist.Ich habe ein Array als,
Input
daher wird dasOnChanges
Ereignis nicht ausgelöst, wenn sich der Inhalt ändert (da die Überprüfung, die Angular durchführt, "einfach" und nicht tief ist, sodass das Array immer noch ein Array ist, obwohl sich der Inhalt des Arrays geändert hat).Anschließend implementiere ich einen benutzerdefinierten Überprüfungscode, um zu entscheiden, ob ich meine Ansicht mit dem geänderten Array aktualisieren möchte.
quelle
Bitte versuchen Sie es mit dieser Methode. Hoffe das hilft
quelle
Sie können auch eine Observable haben, die Änderungen in der übergeordneten Komponente (CategoryComponent) auslöst, und das tun, was Sie in der Subskription in der untergeordneten Komponente tun möchten. (videoListComponent)
quelle
Hier wird ngOnChanges immer ausgelöst, wenn sich Ihre Eingabeeigenschaft ändert:
quelle
Diese Lösung verwendet eine Proxy- Klasse und bietet die folgenden Vorteile:
ngOnChanges()
Anwendungsbeispiel:
Dienstprogrammfunktion:
quelle
Wenn Sie die ngOnChange-Implementierungsmethode og onChange () nicht verwenden möchten, können Sie Änderungen eines bestimmten Elements auch über das valueChanges-Ereignis ETC. abonnieren .
});
Das markForCheck () wurde aufgrund der Verwendung in dieser Deklaration geschrieben:
quelle
Sie können auch einfach einen EventEmitter als Eingabe übergeben. Ich bin mir nicht ganz sicher, ob dies die beste Vorgehensweise ist, obwohl ...
CategoryComponent.ts:
CategoryComponent.html:
Und in VideoListComponent.ts:
quelle