6

I'm starting a new project using boilerplate MEAN provided by MEAN.JS (not .IO).
I'm new to ui-router and I'm having trouble figuring out how to accomplish this scenario:

  • if user is logged in, go to state "home.loggedIn".
  • if user is logged out, go to state "home.loggedOut"
  • the route url is "/" and shouldn't change.

here's how the route provider looks like currently:

angular.module('core').config(['$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
    // Redirect to home view when route not found
    $urlRouterProvider.otherwise('/');

    // Home state routing
    $stateProvider.
    state('home', {
      url: '/',
      abstract: true
    }).
    state('home.loggedOut', {
      templateUrl: 'modules/core/views/home.client.view.html'
    }).
    state('home.loggedIn', {
      templateUrl: 'modules/core/views/dashboard.client.view.html'
    });
  }
]);

I'm looking for something like a pre-save hook in db terms to determine which state to go to. How would that look like?

user1203349
  • 277
  • 6
  • 14

1 Answers1

4

There is a plunker providing behaviour as described above. Firstly, there is a change in a state definition, moving the url from abstract into both child states, and introducing logon state for later checks:

  // Redirect to home view when route not found
  $urlRouterProvider.otherwise('/');

  // Home state routing
  $stateProvider.
  state('home', {
    //url: '/',
    abstract: true,
    template: '<div ui-view=""></div>',
  }).
  state('home.loggedOut', {
    url: '/',
    ...
  }).
  state('home.loggedIn', {
    url: '/',
    ...
  })
  .state('logon', {
    url: '/logon',
    templateUrl: 'tpl.logon.html',
    controller: 'LogonCtrl',
  });

What we do have right now, is definition of 2 states, with a same url. The first will be taken as a default.. and used.

Now, we have to introduce a state change observer, which will redirect to proper sub-state, based on a AuthSvc setting isLoggedIn:

.run(['$rootScope', '$state', 'AuthSvc', 
 function($rootScope, $state, AuthSvc) {

  $rootScope.$on('$stateChangeStart', function(event, toState, toParams
                                                  , fromState, fromParams) {

    // logged out is logged out
    var doRedirectToLoggedOut = !AuthSvc.isLoggedIn 
              && toState.name === "home.loggedIn";

    if (doRedirectToLoggedOut) {
        event.preventDefault();
        $state.go("home.loggedOut");
    }

    // logged in is logged in
    var doRedirectToLoggedIn = AuthSvc.isLoggedIn 
              && toState.name === "home.loggedOut";

    if (doRedirectToLoggedIn) {
        event.preventDefault();
        $state.go("home.loggedIn");
    }
  });
}])

As this example shows in action, until we change isLoggedIn (click on logon link) we are redirected to correct sub-state ... even if we would like to see the other

Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • cool thanks! was hoping there was something more like an option when defining the state that takes a function that does what you describe above when navigating to abstract states. – user1203349 Aug 09 '14 at 03:58
  • hey, one more question: in your plunker, there's already a div with ui-view in index.html. but there is another one when you define the 'home' state. and inspecting the html shows one nested in the other. is this necessary? is the one in index.html the initial one that all views extend from? – user1203349 Aug 10 '14 at 00:11
  • 1
    Easily said: yes it is necessary. Because the loggedOut and loggedIn states do have parent. That means that ui-router is looking for the view inside of the parent (home) not in the root... BUT we can even target the root view in children, check this: http://stackoverflow.com/a/24749774/1679310 or http://stackoverflow.com/a/24982902/1679310 – Radim Köhler Aug 10 '14 at 13:06