In Angular 1.x war UI-Router mein Hauptwerkzeug dafür. Wenn der Router ein Versprechen für "Auflösungs" -Werte zurückgibt, wartet er einfach, bis das Versprechen erfüllt ist, bevor er Anweisungen rendert.
Alternativ kann in Angular 1.x ein Nullobjekt eine Vorlage nicht zum Absturz bringen. Wenn mir also ein vorübergehend unvollständiges Rendern nichts ausmacht, kann ich es einfach $digest
zum Rendern verwenden, nachdem promise.then()
ein ursprünglich leeres Modellobjekt gefüllt wurde.
Wenn möglich, würde ich es vorziehen, mit dem Laden der Ansicht zu warten und die Routennavigation abzubrechen, wenn die Ressource nicht geladen werden kann. Dies erspart mir die Arbeit des "Navigierens". BEARBEITEN: Beachten Sie, dass dies speziell bedeutet, dass diese Frage eine Angular 2-Futures-kompatible oder Best-Practice-Methode dazu anfordert und den "Elvis-Operator" nach Möglichkeit meidet! Daher habe ich diese Antwort nicht ausgewählt.
Keine dieser beiden Methoden funktioniert jedoch in Angular 2.0. Sicherlich ist dafür eine Standardlösung geplant oder verfügbar. Weiß jemand was es ist?
@Component() {
template: '{{cats.captchans.funniest}}'
}
export class CatsComponent {
public cats: CatsModel;
ngOnInit () {
this._http.get('/api/v1/cats').subscribe(response => cats = response.json());
}
}
Die folgende Frage kann dasselbe Problem widerspiegeln: Angular 2-Rendervorlage, nachdem das PROMISE mit Daten geladen wurde . Beachten Sie, dass die Frage keinen Code oder keine akzeptierte Antwort enthält.
Antworten:
Das Paket
@angular/router
hat dieResolve
Eigenschaft für Routen. So können Sie Daten einfach auflösen, bevor Sie eine Routenansicht rendern.Siehe: https://angular.io/docs/ts/latest/api/router/index/Resolve-interface.html
Beispiel aus Dokumenten vom heutigen 28. August 2017:
Jetzt wird Ihre Route erst aktiviert, wenn die Daten aufgelöst und zurückgegeben wurden.
Zugriff auf aufgelöste Daten in Ihrer Komponente
Um zur Laufzeit von Ihrer Komponente aus auf die aufgelösten Daten zuzugreifen, gibt es zwei Methoden. Je nach Ihren Anforderungen können Sie also Folgendes verwenden:
route.snapshot.paramMap
was eine Zeichenfolge zurückgibt, oder dieroute.paramMap
Dies gibt ein Observable zurück, zu dem Sie können.subscribe()
.Beispiel:
Ich hoffe das hilft.
quelle
Versuchen Sie,
{{model?.person.name}}
dies sollte warten, bis das Modell nicht mehr vorhanden ist,undefined
und dann rendern.Winkel 2 bezeichnet diese
?.
Syntax als Elvis-Operator . Ein Verweis darauf in der Dokumentation ist schwer zu finden. Hier ist eine Kopie davon, falls sie geändert / verschoben werden:quelle
Observable
(das gleiche gilt für aPromise
) bereits ausgepackt wurde. Jetzt können Sie nur noch mit unserem bewährten Angular 1.x-Mechanismus, dem Dirty Check, feststellen, wann er sich geändert hat. Vergleichen Sie dies mit der Verwendung von aObservable
, die von derasync
Pipe in der Vorlage selbst unterstützt wird. Angular intern kann (ich vermute es) das Rohr so verdrahten, dass keine Beobachter erforderlich sind, und der Knoten wird nur gerendert, wenn ein Observable eintrifft. Es ist effektiv ein Nachrichtenbus mit ereignisgesteuerten Aktionen.ngIf
Logik implementieren . Ich möchte wirklich, dass der Ansatz "Warten auf das Rendern der Komponente" funktioniert.BEARBEITEN: Das eckige Team hat den @Resolve-Dekorateur veröffentlicht. Es muss noch geklärt werden, wie es funktioniert, aber bis dahin werde ich die Antwort eines anderen hier nehmen und Links zu anderen Quellen bereitstellen:
BEARBEITEN: Diese Antwort funktioniert nur für Angular 2 BETA. Der Router ist zum Zeitpunkt dieser Bearbeitung nicht für Angular 2 RC freigegeben. Ersetzen Sie stattdessen bei Verwendung von Angular 2 RC Verweise auf
router
durchrouter-deprecated
, um den Beta-Router weiterhin zu verwenden.Die Angular2-zukünftige Möglichkeit, dies zu implementieren, erfolgt über den @Resolve-Dekorator. Bis dahin ist das nächstgelegene Faksimile
CanActivate
laut Brandon Roberts Component Decorator. Siehe https://github.com/angular/angular/issues/6611Beta 0 unterstützt zwar nicht die Bereitstellung aufgelöster Werte für die Komponente, ist jedoch geplant, und es gibt auch eine hier beschriebene Problemumgehung : Verwenden von Resolve In Angular2-Routen
Ein Beta 1-Beispiel finden Sie hier: http://run.plnkr.co/BAqA98lphi4rQZAd/#/resolved . Es wird eine sehr ähnliche Problemumgehung verwendet, das
RouteData
Objekt wird jedoch etwas genauer verwendet alsRouteParams
.Beachten Sie außerdem, dass es auch eine Beispielumgehung für den Zugriff auf "aufgelöste" Werte für verschachtelte / übergeordnete Routen und andere Funktionen gibt, die Sie erwarten, wenn Sie den 1.x UI-Router verwendet haben.
Beachten Sie, dass Sie alle Dienste, die Sie dazu benötigen, auch manuell einfügen müssen, da die Angular Injector-Hierarchie derzeit im CanActivate-Dekorator nicht verfügbar ist. Durch einfaches Importieren eines Injektors wird eine neue Injektorinstanz ohne Zugriff auf die Anbieter von erstellt
bootstrap()
. Daher möchten Sie wahrscheinlich eine anwendungsweite Kopie des Bootstrap-Injektors speichern. Brandons zweiter Plunk-Link auf dieser Seite ist ein guter Ausgangspunkt: https://github.com/angular/angular/issues/4112quelle
RouteData
ist auch für den Beta-Router (router-deprecated
) unveränderlich .Stellen Sie mit dem Beobachter einen lokalen Wert ein
... vergessen Sie auch nicht, den Wert mit Dummy-Daten zu initialisieren, um
uninitialized
Fehler zu vermeiden .Dies setzt voraus, dass Model ein Datenmodell ist, das die Struktur Ihrer Daten darstellt.
Ein Modell ohne Parameter sollte eine neue Instanz erstellen, bei der alle Werte initialisiert (aber leer) sind. Auf diese Weise wird beim Rendern der Vorlage vor dem Empfang der Daten kein Fehler ausgegeben.
Wenn Sie die Daten beibehalten möchten, um unnötige http-Anforderungen zu vermeiden, sollten Sie diese im Idealfall in ein Objekt einfügen, das über einen eigenen Beobachter verfügt, den Sie abonnieren können.
quelle
ngIf
auch eine funktionale Problemumgehung ist - und es erfordert weniger doppelten Code als Ihr anderer Vorschlag in Fällen, in denen erwartet wird, dass Ergebnisobjekte komplex sind. Es hat jedoch die gleiche Schwäche, da esObservable
die Vorlage auspackt und erfordert, dass die Vorlage schmutzige Überprüfungen durchführt (oder unnötig neu rendert ). Ich weiß, dass Sie in Ihrem letzten Kommentar nicht damit einverstanden waren, aber wenn Sie weiter darüber nachdenken, werden Sie wahrscheinlich zustimmen. Siehe auch meinen Kommentar zu @tehaaron, dessen Antwort einen ähnlichen Effekt hatte.Observable
Mechanismus in Angular 2 zu unterstützen, und die Leistungsverbesserung auf Seiten mit einer großen Anzahl von Elementen war ein Grund. Es ist eine höhere Leistung und dennoch sehr einfach, als Verbraucher "richtig" zu werden. Also würde ich es gerne benutzen.Eine nette Lösung, die ich gefunden habe, besteht darin, auf der Benutzeroberfläche Folgendes zu tun:
Erst wenn:
vendorServicePricing
,quantityPricing
undservice
geladen werden , die Seite gerendert wird.quelle
?.
"notnull-Operator"Implementieren Sie das
routerOnActivate
in Ihrem@Component
und geben Sie Ihr Versprechen zurück:https://angular.io/docs/ts/latest/api/router/OnActivate-interface.html
BEARBEITEN: Dies funktioniert explizit NICHT, obwohl die aktuelle Dokumentation zu diesem Thema etwas schwer zu interpretieren sein kann. Weitere Informationen finden Sie in Brandons erstem Kommentar hier: https://github.com/angular/angular/issues/6611
BEARBEITEN: Die zugehörigen Informationen auf der ansonsten normalerweise genauen Auth0-Site sind nicht korrekt: https://auth0.com/blog/2016/01/25/angular-2-series-part-4-component-router-in- Tiefe/
BEARBEITEN: Das eckige Team plant zu diesem Zweck einen @Resolve-Dekorateur.
quelle
ngOnInit
den gleichen Effekt?routerOnActivate
ein Versprechen zurückgegeben wird, wartet die Routenänderung, bis das Versprechen erfüllt ist, um * untergeordnete Komponenten zu instanziieren und zu aktivieren.