2015-03-16 11 views
24

W mojej aplikacji angularjs sprawdzam, czy użytkownik ląduje na stronie docelowej i jest już uwierzytelniony, a następnie przekieruje go na stronę główną.

.state('landingpage', { 
      abstract: "true", 
      url: "/landingpage", 
      templateUrl: "app/landingpage/landingpage.html", 
      resolve: { 
       AutoLoginCheck: ['$state', '$window', function ($state, $window) { 

        if($window.localStorage.access_token != null) 
        { 
         if($window.sessionStorage.access_token == null) { 
          $window.sessionStorage.access_token = $window.localStorage.access_token; 
         } 
         UserInfoService.SetUserAuthenticated(true); 

         // it is not redirecting 
         return $state.go('app.home'); 

        } 
       }] 
      } 
     }) 

Problem polega na tym, że choć cały kod resolve powodzeniem działać, użytkownik nie jest uzyskiwanie przekierowany do app.home. Czy ktoś może powiedzieć, dlaczego tak się dzieje?

Uwaga: Stanowa "aplikacja" ma również rozwiązanie, w którym pobiera dane, które mają być wyświetlane w stanie "app.home".

+2

$ stan doesnot pracy z determinacją. –

+1

Dlaczego i czy możesz wyjaśnić, co robi? – Sam

+0

Wierzę, że można to rozwiązać w taki sam sposób, jak odpowiedź [tutaj] (http://stackoverflow.com/a/36728528/846727) – Kunal

Odpowiedz

13

Możliwe są dwa rozwiązania problemu

  • Po pierwsze można emitować zdarzenia i słuchacz będzie obsługiwać przejście stanu. Można zaimplementować słuchacza w dowolnym miejscu kontrolera nadrzędnego

  • drugie można wdrożyć hak $ stateChangeStart i sprawdzić stan przekierowania tam

    $rootScope.$on('$stateChangeStart', function (event, toState) {  
        if (toState.name === 'landingpage') {    
         if (!isAuthenticated()) { // Check if user allowed to transition     
          event.preventDefault(); // Prevent migration to default state     
          $state.go('home.dashboard');   
         } 
         } 
    }); 
    
+0

Gdzie należy umieścić ten warunek? – Sam

+0

Również nie wstrzyknąłeś też stanu $. Nie jestem pewien, czy to działa. – Sam

+0

to jest umieszczone wewnątrz bloku, a $ rootScope i $ state są tam wstawione 'run (function ($ rootScope, $ state) { $ rootScope. $ On ('$ stateChangeStart', funkcja (zdarzenie, toState) { , jeśli (toState.name === 'landing page') { jeśli event.preventDefault() (isAuthenticated (!)); $ state.go ('home.dashboard'); } } }); ' – ptwo

0

Można użyć determinację, aby zapewnić kontroler z zawartością lub dane niestandardowe dla stanu. resolve to opcjonalna mapa zależności, które należy wprowadzić do kontrolera.

Możesz mieć kontroler, który sprawdza AuthState i odpowiednio przekierowuje.

 .state('landingpage', { 
     abstract: "true", 
     url: "/landingpage", 
     templateUrl: "app/landingpage/landingpage.html", 
     resolve: { 
      AutoLoginCheck: ['$window', function ($window) { 

       if($window.localStorage.access_token != null) 
       { 
        if($window.sessionStorage.access_token == null) { 
         $window.sessionStorage.access_token = $window.localStorage.access_token; 
        } 

        //assuming userInfoService does the authentication 
        var isAuthenticated = userInfoService.SetUserAuthenticated(true); 
        return isAuthenticated; 

       } 
      }] 
     }, 
     controller: ['$state','AutoLoginCheck', function($state, AutoLoginCheck){ 
      if(AutoLoginCheck){ 
      //authenticated 
      $state.go('app.home'); 
      } else { 
      //redirect to unauthenticated page 
      $state.go('....'); 
      } 
     }] 
    }) 
+0

I lubię to podejście, ale przypuśćmy, że muszę zabezpieczyć moje trasy i muszę sprawdzić autoryzację użytkownika na każdej trasie, do której ma dostęp. Musiałbym to powtórzyć wszędzie, w porządku, mam wiele tras w mojej aplikacji – Sam

+0

Też próbowałem tego i strona przekierowana poprawnie, ale nie przed wyświetleniem bieżącej strony przez ułamek sekundy.Czy istnieje sposób, aby zatrzymać kierowanie do bieżącego stanu, podczas gdy kontroler przekierowuje? – Sam

+0

Proponuję, aby logika auth/przekierowania była na poziomie abstrakcji poziomu głównego, a więc wszystkie stany, które są chronione, będą działały zagnieżdżone. Ale to wymagałoby zaktualizowania wszystkich twoich stanów. Aby dodać opóźnienia, można rozważyć użycie limitu czasu przed naciśnięciem przycisku auth. – Karthik

26
.state('landingpage', { 
      abstract: "true", 
      url: "/landingpage", 
      templateUrl: "app/landingpage/landingpage.html", 
      resolve: { 
       AutoLoginCheck: ['$state','$window', '$q','$timeout', function ($state, $window,$q,$timeout) { 

        if($window.localStorage.access_token != null) 
        { 
         if($window.sessionStorage.access_token == null) { 
          $window.sessionStorage.access_token = $window.localStorage.access_token; 
         } 
         UserInfoService.SetUserAuthenticated(true); 


         $timeout(function() { 
          $state.go('app.home') 
         },0); 
         return $q.reject() 

        } 
       }] 
      } 
     }) 

To będzie pracować dla Ciebie.

+1

Czy możesz również dodać wyjaśnienie? – Robert

+3

@Robert: W środku rozstrzygnięcie jedyną możliwą rzeczą jest odrzucenie lub rozwiązanie obietnicy. Myślę, że stan.go() nie jest możliwe, chyba że dodamy go w callstack przy użyciu limitu czasu. –

+2

Zrobiłem podobny do tego, ale bez timeoutu w następujący sposób: 'return $ q.reject(). Catch (function() {$ state.go ('app.home'); return $ q.reject();) 'wtedy obniżasz liczbę wstrzyknięć – Gustav

13

Zamiast tego można użyć $location.url('/').

0

Jest to stary wątek, ale używam $ location.path(), aby wykonać przekierowanie wewnątrz state.resolve() blokuje

0

Zresztą rozwiązać czeka na państwa obietnicy. Najlepszą rzeczą, co można zrobić, to obietnica powrotu limitu czasu i dodać do swojego stanu:

resolve: { 
    AutoLoginCheck: ['$state', '$window', '$timeout', '$q', function ($state, $window, $timeout, $q) { 
     var deferred = $q.defer(); 
     if(user.isLogin()){ 
      deferred.resolve(); 
     }else{ 
      $timeout(function(){ 
      $state.go('app.home'); 
      } 
      deferred.reject(); 
     } 
     return deferred.promise; 
    }]