$ routeProvider resolve właściwość umożliwia opóźnienie zmiany trasy, aż dane zostaną załadowane.
Najpierw zdefiniuj trasę z resolve
takim atrybutem.
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'});
}]);
zauważ, że resolve
właściwość jest zdefiniowana na trasie.
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;
}
}
Zauważ, że definicja kontrolera zawiera obiekt rozstrzygający, który deklaruje rzeczy, które powinny być dostępne dla konstruktora kontrolera. Tutaj phones
jest wstrzykiwany do kontrolera i jest zdefiniowany we resolve
właściwości.
resolve.phones
Funkcja jest odpowiedzialna za zwrot obietnicę. Wszystkie obietnice są zbierane, a zmiana trasy jest opóźniona do momentu, aż wszystkie obietnice zostaną rozwiązane.
Działające demo: http://mhevery.github.com/angular-phonecat/app/#/phones
Źródło: https://github.com/mhevery/angular-phonecat/commit/ba33d3ec2d01b70eb5d3d531619bf90153496831
angular.controller()
definicjach kontrolera typu? W$routeProvider
rzeczy, pomyślałem, trzeba było używać nazw ciągów kontrolerów.angular.controller()
, możesz przypisać wynik działania tej funkcji do zmiennej (var MyCtrl = angular.controller(...)
), a następnie pracować z nią dalej (MyCtrl.loadData = function(){..}
). Sprawdź wideo eggheadOto minimalny działający przykład, który działa w Angular 1.0.2
Szablon:
JavaScript:
http://jsfiddle.net/dTJ9N/3/
Usprawniona wersja:
Ponieważ $ http () już zwraca obietnicę (inaczej odroczoną), tak naprawdę nie musimy tworzyć własnej. Możemy więc uprościć MyCtrl. zdecydować się na:
Wynik $ http () zawiera dane , status , nagłówki i obiekty konfiguracji , dlatego musimy zmienić treść MyCtrl na:
http://jsfiddle.net/dTJ9N/5/
źródło
Unknown provider: datasetsProvider <- datasets
function($http) { return $http({method: 'GET', url: '/someUrl'}) .then( function(data){ return data;}, function(reason){return 'error value';} ); }
Widzę, że niektórzy ludzie pytają, jak to zrobić za pomocą metody angular.controller z przyjaznym dla minimalizacji zastrzykiem zależności. Odkąd właśnie to uruchomiłem, czułem się zobowiązany do powrotu i pomocy. Oto moje rozwiązanie (zaczerpnięte z pierwotnego pytania i odpowiedzi Misko):
Ponieważ ten kod pochodzi z pytania / najpopularniejszej odpowiedzi, nie został przetestowany, ale powinien wysłać cię we właściwym kierunku, jeśli już wiesz, jak zrobić kod kątowy przyjazny dla minimalizacji. Jedyną częścią, której mój własny kod nie wymagał, było wstrzyknięcie „Telefonu” do funkcji rozstrzygania dla „telefonów”, a ja w ogóle nie użyłem żadnego obiektu „opóźnienia”.
Polecam również ten film na youtube http://www.youtube.com/watch?v=P6KITGRQujQ&list=UUKW92i7iQFuNILqQOUOCrFw&index=4&feature=plcp , co bardzo mi pomogło
Jeśli cię to zainteresuje, postanowiłem wkleić własny kod (napisany w coffeescript), abyś mógł zobaczyć, jak to działa.
Do twojej wiadomości, z góry używam ogólnego kontrolera, który pomaga mi zrobić CRUD na kilku modelach:
źródło
resolve
funkcji w kontrolerze, w najnowszych wersjach Angulara? Czyli trzeba to zadeklarować bezpośrednio w konfiguracji, tak jak jest tutaj?$defer
usługi, zwróć uwagę, że w wersji 1.5.7 AngularJS,$timeout
zamiast tego chcesz użyć .To zatwierdzenie , które jest częścią wersji 1.1.5 i nowszych, udostępnia
$promise
obiekt$resource
. Wersje ngResource, w tym ten zatwierdzenie, pozwalają na rozwiązywanie takich zasobów:$ routeProvider
kontroler
źródło
GET '/api/1/apps/:appId'
->App.get({id: $routeParams.appId}).$promise();
Nie mogę użyć w ten sposób$route
do swojego rozwiązania i używasz$route.current.params
. Uważaj,$routeParams
wciąż wskazuje starą trasę.Ten fragment kodu jest przyjazny dla wstrzykiwania zależności (używam go nawet w połączeniu ngmin i uglify ) i jest bardziej eleganckim rozwiązaniem opartym na domenie .
Poniższy przykład rejestruje zasób telefonu i stały phoneRoutes , który zawiera wszystkie informacje o routingu dla tej domeny (telefonu). W podanej odpowiedzi nie podobało mi się położenie logiki rozwiązywania - moduł główny nie powinien nic wiedzieć ani przejmować się sposobem dostarczania argumentów zasobów do kontrolera. W ten sposób logika pozostaje w tej samej domenie.
Uwaga: jeśli używasz ngmin (a jeśli nie: powinieneś), musisz tylko napisać funkcje rozpoznawania z konwencją tablic DI.
Następnym elementem jest wstrzyknięcie danych routingu, gdy moduł jest w stanie konfiguracji i zastosowanie go do $ routeProvider .
Testowanie konfiguracji trasy za pomocą tej konfiguracji jest również dość łatwe:
Możesz to zobaczyć w pełnej krasie w moim ostatnim (nadchodzącym) eksperymencie . Chociaż ta metoda działa dla mnie dobrze, naprawdę zastanawiam się, dlaczego $ injector nie opóźnia budowy czegokolwiek, gdy wykrywa zastrzyk czegokolwiek , co jest przedmiotem obietnicy ; znacznie ułatwiłoby to tak bardzoOOOOOOOooOOOOO.
Edycja: używane Angular v1.2 (rc2)
źródło
I really wonder why the $injector isn't delaying construction of anything when it detects injection of anything that is a promise object
Domyślam się, że pominęli tę funkcjonalność, ponieważ może zachęcać do wzorców projektowych, które negatywnie wpływają na czas reakcji aplikacji. Idealna aplikacja w ich opinii jest naprawdę asynchroniczna, więc rozwiązywanie powinno być przypadkowe.Opóźnianie pokazania trasy z pewnością doprowadzi do asynchronicznej plątaniny ... dlaczego nie po prostu śledzić status ładowania głównego obiektu i używać go w widoku. Na przykład w kontrolerze możesz użyć zarówno wywołań powodzenia, jak i błędów w ngResource:
Następnie w widoku możesz zrobić cokolwiek:
źródło
Pracowałem z powyższego kodu Misko i właśnie to zrobiłem. Jest to bardziej aktualne rozwiązanie, ponieważ
$defer
zostało zmienione na$timeout
. Zastąpienie$timeout
spowoduje jednak, że upłynie limit czasu (w kodzie Misko: 1 sekunda), a następnie zwróci dane z nadzieją, że czas zostanie rozwiązany. W ten sposób zwraca jak najszybciej.źródło
Korzystanie z AngularJS 1.1.5
Aktualizacja funkcji „telefonów” w odpowiedzi Justena przy użyciu składni AngularJS 1.1.5 .
Oryginalny:
Zaktualizowano:
Znacznie krócej dzięki zespołowi Angular i współpracownikom. :)
To także odpowiedź Maximiliana Hoffmanna. Najwyraźniej zatwierdzenie przeszło do wersji 1.1.5.
źródło
$promise
w dokumentach . Być może został wyjęty od wersji 2.0 +.Możesz użyć właściwości $ routeProvider resolver do opóźnienia zmiany trasy do momentu załadowania danych.
Zauważ, że
resolve
właściwość jest zdefiniowana na trasie.EntitiesCtrlResolve
iEntityCtrlResolve
jest stałymi obiektami zdefiniowanymi w tym samym pliku coEntitiesCtrl
iEntityCtrl
kontrolery.źródło
Podoba mi się pomysł darkportera, ponieważ zespołowi deweloperów AngularJS będzie łatwo zrozumieć i od razu pracować.
Stworzyłem tę adaptację, która wykorzystuje 2 elementy div, jedną dla paska ładowania, a drugą dla rzeczywistej zawartości wyświetlanej po załadowaniu danych. Obsługa błędów byłaby wykonywana gdzie indziej.
Dodaj flagę „ready” do $ scope:
W widoku HTML:
Zobacz także: Dokumenty paska postępu Boostrap
źródło
Podobały mi się powyższe odpowiedzi i wiele się od nich nauczyłem, ale w większości powyższych odpowiedzi brakuje czegoś.
Utknąłem w podobnym scenariuszu, w którym rozwiązywałem adres URL z danymi, które są pobierane w pierwszym żądaniu z serwera. Problem, z którym się spotkałem, polegał na tym, że jeśli taka jest obietnica
rejected
.I był przy użyciu niestandardowego dostawcy, który używany do zwróci
Promise
który został rozwiązany przezresolve
z$routeProvider
w czasie fazy config.Chciałbym tutaj podkreślić, że koncepcja
when
tego robi coś takiego.Widzi adres URL w pasku adresu URL, a następnie odpowiedni
when
blok w nazwie kontrolera, a widok jest do tej pory odsyłany tak dobrze.Powiedzmy, że mam następujący kod fazy konfiguracji.
Na adresie URL root w przeglądarce wywoływany
otherwise
jest pierwszy blok uruchamiania, w przeciwnym razie wywoływany.Wyobraźmy sobie scenariusz, w którym uderzyłem rootUrl w
AuthServicePrivider.auth()
funkcji paska adresu .Powiedzmy, że Obietnica zwrócona jest w stanie odrzucenia, co wtedy ???
Nic się nie renderuje.
Otherwise
blok nie zostanie wykonany tak, jak w przypadku dowolnego adresu URL, który nie jest zdefiniowany w bloku konfiguracji i nie jest znany fazie konfiguracji angularJs.Będziemy musieli poradzić sobie ze zdarzeniem, które zostanie zwolnione, gdy ta obietnica nie zostanie rozwiązana. W przypadku awarii
$routeChangeErorr
zostaje zwolniony$rootScope
.Można go przechwycić, jak pokazano w kodzie poniżej.
IMO Generalnie dobrym pomysłem jest umieszczenie kodu śledzenia zdarzeń w bloku uruchamiania aplikacji. Ten kod jest uruchamiany tuż po fazie konfiguracji aplikacji.
W ten sposób poradzimy sobie z niepowodzeniem obietnicy w fazie konfiguracji.
źródło
Miałem złożony wielopoziomowy interfejs panelu przesuwnego z wyłączoną warstwą ekranu. Tworzenie dyrektywy dotyczącej wyłączania warstwy ekranu, która tworzyłaby zdarzenie click, aby wykonać stan podobny do
wywoływały efekt trzepotania. history.back () zamiast tego działało dobrze, jednak w moim przypadku nie zawsze wraca do historii. Przekonałem się więc, że jeśli po prostu utworzę atrybut href na moim ekranie wyłączania zamiast state.go, działałoby to jak urok.
Dyrektywa „wstecz”
app.js Po prostu zapisuję poprzedni stan
źródło
Jednym z możliwych rozwiązań może być użycie dyrektywy ng-cloak z elementem, w którym używamy modeli np
Myślę, że ten wymaga najmniejszego wysiłku.
źródło