2014-07-05 6 views
6

Moja konfiguracja ui-router jest to:Angular ui-router: Jak odroczyć renderowanie szablonu do czasu zakończenia autoryzacji?

$stateProvider 
    .state('app', { 
    url: '/app', 
    abstract: true, 
    templateUrl: 'sidemenu/sidemenu.html', 
    controller: 'SideMenuCtrl' 
    }) 
    .state('login', { 
    url: '/login', 
    templateUrl: 'login/login.html', 
    controller: 'LoginCtrl' 
    }) 
    .state('app.dashboard', { 
    url: '/dashboard', 
    views: { 
     menuContent: { 
     templateUrl: 'dashboard/dashboard.html', 
     controller: 'DashboardCtrl' 
     } 
    } 
    }) 
    [More states here] 

$urlRouterProvider.otherwise('/app/dashboard'); 

Kiedy użytkownik przechodzi do /app/dashboard Chciałbym sprawdzić, czy są one dopuszczone, a następnie:

  • przekierować do /login jeśli nie są upoważnione, lub
  • pozwalają zobaczyć pulpit jeżeli są one dopuszczone

wydaje się to do rade: (w oparciu o this example)

$rootScope.$on('$stateChangeSuccess', function(event) { 
    var path = $location.path(); 

    if (path === '/login') { 
    return; 
    } 

    // Halt state change from even starting 
    event.preventDefault(); 

    Auth.getCurrentUser().then(function(currentUser) { 
    if (currentUser === null) { 
     $state.go('login'); 
    } else { 
     // Continue with the update and state transition 
     $urlRouter.sync(); 
    } 
    }); 
}); 

Jedyny problem z tego rozwiązania jest to, że jeśli nieautoryzowany użytkownik nawiguje do deski rozdzielczej, szablon deska rozdzielcza jest widoczna pierwsza. Dopiero po otrzymaniu odpowiedzi autoryzacyjnej zmienia się w szablon logowania.

Czy istnieje sposób, aby nie wyświetlać deski rozdzielczej, gdy autoryzujemy użytkownika?

Próbowałem również zmienić $stateChangeSuccess na $stateChangeStart, ale tak naprawdę nie działało (routing wydaje się być całkowicie zepsuty).

Odpowiedz

8

Co powiesz na użycie bloku rozstrzygania?

.state('app.dashboard', { 
    url: '/dashboard', 
    views: { 
     menuContent: { 
      templateUrl: 'dashboard/dashboard.html', 
      controller: 'DashboardCtrl', 
      resolve: { 
       login: function($q, Auth) { 
        var deferred = $q.defer(); 
        Auth.getCurrentUser().then(function(currentUser) { 
         if (currentUser == null) { 
          deferred.reject(); 
         } else { 
          deferred.resolve(); 
         } 
        }); 
        return deferred.promise; 
       } 
      } 
     } 
    } 
}) 

Zmiana stanu nie nastąpi, dopóki obietnica nie zostanie rozwiązana, dlatego szablon nie powinien być wyświetlany. Odrzucenie obietnicy spowoduje podniesienie wartości $stateChangeError zgodnie z this answer, więc trzeba będzie obsłużyć ten błąd i przekierować na stronę logowania.

+0

Nie można wykonać połączenia z serwerem dla każdej strony, jeśli jest to olbrzymia aplikacja. Próbowałem użyć $ rootScope.username, ale to nie zadziałało? Jakieś pomysły ? –

+0

'Auth.getCurrentUser()' może łatwo buforować dane użytkownika (chociaż wtedy musisz zaimplementować klienta timeout jeśli potrzebujesz) – ivarni

0

Możesz użyć rozwiązania na trasach i odrzucić obietnicę, gdy użytkownik nie jest zalogowany, więc kontroler nigdy nie zostanie osiągnięty.