Die Auflösungseigenschaft $ routeProvider ermöglicht die Verzögerung der Routenänderung , bis Daten geladen werden.
Definieren Sie zunächst eine Route mit einem solchen resolve
Attribut.
angular.module('phonecat', ['phonecatFilters', 'phonecatServices', 'phonecatDirectives']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/phones', {
templateUrl: 'partials/phone-list.html',
controller: PhoneListCtrl,
resolve: PhoneListCtrl.resolve}).
when('/phones/:phoneId', {
templateUrl: 'partials/phone-detail.html',
controller: PhoneDetailCtrl,
resolve: PhoneDetailCtrl.resolve}).
otherwise({redirectTo: '/phones'});
}]);
Beachten Sie, dass die resolve
Eigenschaft auf der Route definiert ist.
function PhoneListCtrl($scope, phones) {
$scope.phones = phones;
$scope.orderProp = 'age';
}
PhoneListCtrl.resolve = {
phones: function(Phone, $q) {
// see: https://groups.google.com/forum/?fromgroups=#!topic/angular/DGf7yyD4Oc4
var deferred = $q.defer();
Phone.query(function(successData) {
deferred.resolve(successData);
}, function(errorData) {
deferred.reject(); // you could optionally pass error data here
});
return deferred.promise;
},
delay: function($q, $defer) {
var delay = $q.defer();
$defer(delay.resolve, 1000);
return delay.promise;
}
}
Beachten Sie, dass die Controller-Definition ein Auflösungsobjekt enthält, das Dinge deklariert, die dem Controller-Konstruktor zur Verfügung stehen sollen. Hier phones
wird das in den Controller injiziert und in der resolve
Eigenschaft definiert .
Die resolve.phones
Funktion ist für die Rückgabe eines Versprechens verantwortlich. Alle Versprechen werden gesammelt und die Routenänderung wird verzögert, bis alle Versprechen gelöst sind.
Arbeitsdemo: http://mhevery.github.com/angular-phonecat/app/#/phones
Quelle: https://github.com/mhevery/angular-phonecat/commit/ba33d3ec2d01b70eb5d3d531619bf90153496831
angular.controller()
Typcontroller-Definitionen verwendet? In dem$routeProvider
Zeug dachte ich, Sie müssten String-Namen von Controllern verwenden.angular.controller()
, können Sie das Ergebnis dieser Funktion einer Variablen (var MyCtrl = angular.controller(...)
) zuweisen und dann weiter damit arbeiten (MyCtrl.loadData = function(){..}
). Schauen Sie sich das Video von Egghead anHier ist ein minimales Arbeitsbeispiel, das für Angular 1.0.2 funktioniert
Vorlage:
JavaScript:
http://jsfiddle.net/dTJ9N/3/
Optimierte Version:
Da $ http () bereits ein Versprechen zurückgibt (auch als verzögert bezeichnet), müssen wir eigentlich kein eigenes erstellen. So können wir MyCtrl vereinfachen. beschließen zu:
Das Ergebnis von $ http () enthält Daten , Status , Header und Konfigurationsobjekte. Daher müssen wir den Hauptteil von MyCtrl in Folgendes ändern:
http://jsfiddle.net/dTJ9N/5/
quelle
Unknown provider: datasetsProvider <- datasets
function($http) { return $http({method: 'GET', url: '/someUrl'}) .then( function(data){ return data;}, function(reason){return 'error value';} ); }
Ich sehe einige Leute fragen, wie dies mit der Angular.Controller-Methode mit minifizierungsfreundlicher Abhängigkeitsinjektion zu tun ist. Da ich gerade damit angefangen habe, fühlte ich mich verpflichtet, zurückzukommen und zu helfen. Hier ist meine Lösung (übernommen aus der ursprünglichen Frage und Miskos Antwort):
Da dieser Code von der Frage / beliebtesten Antwort abgeleitet ist, ist er nicht getestet, sollte Sie jedoch in die richtige Richtung leiten, wenn Sie bereits verstehen, wie man einen minifizierungsfreundlichen Winkelcode erstellt. Der eine Teil, den mein eigener Code nicht benötigte, war das Einfügen von "Telefon" in die Auflösungsfunktion für "Telefone", und ich habe überhaupt kein "Verzögerungs" -Objekt verwendet.
Ich empfehle auch dieses Youtube-Video http://www.youtube.com/watch?v=P6KITGRQujQ&list=UUKW92i7iQFuNILqQOUOCrFw&index=4&feature=plcp , das mir sehr geholfen hat
Sollte es Sie interessieren, habe ich beschlossen, auch meinen eigenen Code (geschrieben in Coffeescript) einzufügen, damit Sie sehen können, wie ich ihn zum Laufen gebracht habe.
Zu Ihrer Information, im Voraus verwende ich einen generischen Controller, der mir hilft, CRUD bei mehreren Modellen durchzuführen:
quelle
resolve
in neueren Versionen von Angular jetzt unmöglich ist, auf eine Funktion im Controller zu verweisen ? Also muss es direkt in der Konfiguration deklariert werden, wie es hier ist?$defer
Beachten Sie für alle anderen Benutzer, die Fehler bezüglich eines nicht definierten Dienstes erhalten, dass Sie in Version 1.5.7 von AngularJS$timeout
stattdessen verwenden möchten .Dieses Commit , das Teil von Version 1.1.5 und höher ist, macht das
$promise
Objekt von verfügbar$resource
. Versionen von ngResource, einschließlich dieses Commits, ermöglichen das Auflösen von Ressourcen wie folgt:$ routeProvider
Regler
quelle
GET '/api/1/apps/:appId'
->App.get({id: $routeParams.appId}).$promise();
kann ich nicht so verwenden$route
zu Ihrer Entschlossenheit und Verwendung$route.current.params
. Seien Sie vorsichtig,$routeParams
zeigt immer noch auf die alte Route.Dieser Ausschnitt ist Dependency Injection freundlich (ich es auch verwende in Kombination von ngmin und uglify ) und es ist eine elegante Domain angetrieben basierte Lösung.
Das unten stehende Beispiel Register eine Telefonressource und eine Konstante phoneRoutes , die alle Ihre Routing - Informationen für diese (Telefon) Domäne enthält. Etwas , was ich tat es nicht wie in der mitgelieferten Antwort war die Lage der Entschlossenheit Logik - das Hauptmodul soll nicht wissen nichts oder über die Art und Weise gestört werden , die Ressourcen Argumente an die Steuerung zur Verfügung gestellt werden. Auf diese Weise bleibt die Logik in derselben Domäne.
Hinweis: Wenn Sie ngmin verwenden (und wenn nicht: sollten Sie), müssen Sie die Auflösungsfunktionen nur mit der DI-Array-Konvention schreiben.
Das nächste Stück ist das Injizieren der Routing-Daten, wenn sich das Modul im Konfigurationsstatus befindet, und das Anwenden auf den $ routeProvider .
Das Testen der Routenkonfiguration mit diesem Setup ist ebenfalls recht einfach:
Sie können es in meinem letzten (bevorstehenden) Experiment in voller Pracht sehen . Obwohl diese Methode für mich gut funktioniert, frage ich mich wirklich, warum der $ -Injektor die Konstruktion von nichts verzögert , wenn er die Injektion von etwas erkennt , das ein vielversprechendes Objekt ist. es würde die Dinge sooooooooooooooo viel einfacher machen.
Bearbeiten: verwendet Angular v1.2 (rc2)
quelle
I really wonder why the $injector isn't delaying construction of anything when it detects injection of anything that is a promise object
Ich vermute, sie haben diese Funktionalität weggelassen, weil sie möglicherweise Entwurfsmuster fördert, die sich negativ auf die Reaktionsfähigkeit von Apps auswirken. Die ideale App in ihrem Kopf ist eine wirklich asynchrone, daher sollte das Auflösen ein Randfall sein.Wenn Sie die Route verzögern, führt dies mit Sicherheit zu einem asynchronen Gewirr. Verfolgen Sie einfach den Ladestatus Ihrer Hauptentität und verwenden Sie diesen in der Ansicht. In Ihrem Controller können Sie beispielsweise sowohl die Erfolgs- als auch die Fehlerrückrufe für ngResource verwenden:
Dann könnten Sie in der Ansicht alles tun:
quelle
Ich habe nach Miskos Code oben gearbeitet und das habe ich damit gemacht. Dies ist eine aktuellere Lösung, da
$defer
auf geändert wurde$timeout
. Das Ersetzen$timeout
wartet jedoch auf die Zeitüberschreitung (in Miskos Code 1 Sekunde) und gibt dann die Daten zurück, in der Hoffnung, dass sie rechtzeitig behoben werden. Auf diese Weise wird so schnell wie möglich zurückgegeben.quelle
Verwenden von AngularJS 1.1.5
Aktualisieren der 'Telefone'-Funktion in Justens Antwort mithilfe der AngularJS 1.1.5- Syntax.
Original:
Aktualisiert:
Viel kürzer dank des Angular-Teams und der Mitwirkenden. :) :)
Dies ist auch die Antwort von Maximilian Hoffmann. Anscheinend hat dieses Commit es in 1.1.5 geschafft.
quelle
$promise
in den Dokumenten finden . Es wurde möglicherweise ab Version 2.0 entfernt.Sie können die Eigenschaft $ routeProvider auflösen verwenden, um die Routenänderung zu verzögern, bis Daten geladen werden.
Beachten Sie, dass die
resolve
Eigenschaft auf der Route definiert ist.EntitiesCtrlResolve
undEntityCtrlResolve
sind konstante Objekte, die in derselben Datei wieEntitiesCtrl
undEntityCtrl
Controller definiert sind.quelle
Ich mag die Idee von darkporter, weil es für ein Entwicklerteam, das neu bei AngularJS ist, leicht sein wird, sie sofort zu verstehen und zu arbeiten.
Ich habe diese Anpassung erstellt, die 2 Divs verwendet, einen für die Laderleiste und einen für den tatsächlichen Inhalt, der nach dem Laden der Daten angezeigt wird. Die Fehlerbehandlung würde an anderer Stelle erfolgen.
Fügen Sie $ scope ein 'ready'-Flag hinzu:
In der HTML-Ansicht:
Siehe auch: Boostrap-Fortschrittsbalken-Dokumente
quelle
Ich mochte die obigen Antworten und habe viel von ihnen gelernt, aber in den meisten der obigen Antworten fehlt etwas.
Ich steckte in einem ähnlichen Szenario fest, in dem ich die URL mit einigen Daten auflöste, die in der ersten Anforderung vom Server abgerufen wurden. Das Problem, mit dem ich konfrontiert war, war, was ist, wenn das Versprechen ist
rejected
.Ich war mit einem benutzerdefinierten Anbieter , die ein benutzten zurückzukehren ,
Promise
die durch die aufgelöste wurdenresolve
von$routeProvider
zum Zeitpunkt der Konfigurationsphase.Was ich hier hervorheben möchte, ist das Konzept, dass
when
es so etwas tut.Es sieht die URL in der URL-Leiste und dann den entsprechenden
when
Block im aufgerufenen Controller und die Ansicht wird bisher so gut verwiesen.Nehmen wir an, ich habe folgenden Konfigurationsphasencode.
Bei der Root-URL im Browser wird der erste Block des Laufs aufgerufen, andernfalls
otherwise
wird er aufgerufen.Stellen wir uns ein Szenario vor, in dem ich rootUrl in der Adressleistenfunktion drücke
AuthServicePrivider.auth()
.Sagen wir Versprechen zurück in wird ablehnen Zustand , was dann ???
Es wird überhaupt nichts gerendert.
Otherwise
Der Block wird nicht ausgeführt, wie dies für eine URL der Fall ist, die nicht im Konfigurationsblock definiert ist und der Konfigurationsphase von angleJs unbekannt ist.Wir müssen das Ereignis behandeln, das ausgelöst wird, wenn dieses Versprechen nicht gelöst wird. Bei einem Fehler
$routeChangeErorr
wird ausgelöst$rootScope
.Es kann wie im folgenden Code gezeigt erfasst werden.
IMO Es ist im Allgemeinen eine gute Idee, den Ereignisverfolgungscode in den Ausführungsblock der Anwendung einzufügen. Dieser Code wird unmittelbar nach der Konfigurationsphase der Anwendung ausgeführt.
Auf diese Weise können wir Versprechensfehler zum Zeitpunkt der Konfigurationsphase behandeln.
quelle
Ich hatte eine komplexe mehrstufige Gleitfeldoberfläche mit deaktivierter Bildschirmebene. Erstellen einer Direktive zum Deaktivieren der Bildschirmebene, die ein Klickereignis zum Ausführen des Status "Gefällt mir" erstellt
erzeugten einen Flicking-Effekt. history.back () stattdessen hat es gut funktioniert, aber in meinem Fall ist es nicht immer wieder in der Geschichte. Was ich also herausfinde, ist, dass, wenn ich einfach ein Attribut href auf meinem Deaktivierungsbildschirm anstelle von state.go erstelle, es wie ein Zauber funktioniert hat.
Richtlinie "zurück"
app.js Ich speichere nur den vorherigen Status
quelle
Eine mögliche Lösung könnte darin bestehen, die ng-cloak-Direktive mit dem Element zu verwenden, in dem wir die Modelle verwenden, z
Ich denke, das kostet am wenigsten Mühe.
quelle