2013-01-08 18 views
89

Mam usługę AuthService, która loguje użytkownika, zwraca obiekt json użytkownika. Chcę tylko ustawić ten obiekt i odzwierciedlić wszystkie zmiany w aplikacji (stan zalogowania/wylogowania) bez konieczności odświeżania strony.Jak zapisać bieżący kontekst użytkownika w Angular?

Jak to zrobić z AngularJS?

Odpowiedz

177

Najprostszym sposobem na osiągnięcie tego celu jest skorzystanie z usługi. Na przykład:

app.factory('AuthService', function() { 
    var currentUser; 

    return { 
    login: function() { ... }, 
    logout: function() { ... }, 
    isLoggedIn: function() { ... }, 
    currentUser: function() { return currentUser; } 
    ... 
    }; 
}); 

Możesz odwołać się do tego w dowolnym ze swoich kontrolerów. Poniższy kod obserwuje zmiany wartości z usługi (przez wywołanie określonej funkcji), a następnie synchronizuje zmienione wartości z zakresem.

app.controller('MainCtrl', function($scope, AuthService) { 
    $scope.$watch(AuthService.isLoggedIn, function (isLoggedIn) { 
    $scope.isLoggedIn = isLoggedIn; 
    $scope.currentUser = AuthService.currentUser(); 
    }); 
}); 

Oczywiście, możesz użyć tych informacji, ale uznasz to za stosowne; na przykład w dyrektywach, szablonach itp. Możesz powtórzyć to (dostosowane do tego, co musisz zrobić) w kontrolerach menu, itp. Wszystko zostanie zaktualizowane automatycznie po zmianie stanu usługi.

Coś bardziej konkretnego zależy od implementacji.

Mam nadzieję, że to pomoże!

+1

Tak też myślałem, ale jestem ciekawa, jak działa fabryka. Czy nie otrzymamy innego kontekstu currentUser za każdym razem, gdy tworzony jest kontroler i prosi o AuthService? Być może po prostu nie wiem, w jaki sposób Angular haczyka. Idealnie byśmy mieli jeden kontekst. Jako alternatywę myślałem o używaniu sklepu ngCookies (nie mój ulubiony pomysł) lub pamięci przeglądarki (nie jest to jeszcze dobrze obsługiwane). –

+28

@ChrisNicola W rzeczywistości w AngularJS wszystkie usługi są singletons. Tak więc usługa jest tworzona po raz pierwszy, kiedy jest żądana (tj. Przez kontroler lub inną usługę), a wszystkie kolejne żądania jej zwracają dokładnie to samo wystąpienie. –

+0

@JoshDavidMiller Masz właściwość 'isLoggedIn' jako funkcję? Czy to nie byłby boolean? – nicholas

5

Chciałbym zmienić dobrą odpowiedź Josh, dodając, że ponieważ usługa AuthService jest zwykle interesująca dla każdego (powiedzmy, każdy, ale widok logowania powinien zniknąć, jeśli nikt nie jest zalogowany), może prostszą alternatywą byłoby powiadomienie zainteresowanych strony używające $rootScope.$broadcast('loginStatusChanged', isLoggedIn); (1) (2), podczas gdy zainteresowane strony (takie jak kontrolery) będą nasłuchiwać przy użyciu $scope.$on('loginStatusChanged', function (event, isLoggedIn) { $scope.isLoggedIn = isLoggedIn; }.

(1) $rootScope jest wstrzykiwany jako argument usługi

(2) Należy zauważyć, że w prawdopodobnym przypadku asynchronicznego procesu logowania, będziemy chcieli, aby powiadomić kątowa, że ​​transmisja będzie zmienić ten stan rzeczy, przez włączenie go w funkcję $rootScope.$apply().

Teraz, mówiąc o utrzymywaniu kontekstu użytkownika w każdym/wielu kontrolerach, możesz nie być usatysfakcjonowany, słuchając zmian logowania w każdym z nich, i wolisz słuchać tylko w najwyższym kontrolerze logowania, a następnie dodawać inne świadome logowanie kontrolery jako dzieci/wbudowane kontrolery tego. W ten sposób kontroler podrzędny będzie mógł zobaczyć odziedziczone właściwości rodzica $ scope, takie jak kontekst użytkownika.

+4

Rewizja za nieprawidłowe wyjaśnienie funkcji fabrycznej. To nieporozumienie zostało już omówione w [this comment] (http://stackoverflow.com/questions/14206492/how-do-i-store-a-current-user-context-in-angular/14206567#comment20831205_14206567) kilka miesięcy przed tobą opublikował twoją odpowiedź. –

Powiązane problemy