29

The landing page of my app has two states: home-public, home-logged-in. Now I want to show both states on the same URL, but let the controller and template depend on the user session (is the user logged in or not?).

Is there a way to achieve this?

JacobF
  • 2,305
  • 3
  • 24
  • 36

2 Answers2

51

You could have a base state that controls which state to load, and you could simply have the child stated of that base state not have urls:

.state('home', {
  url: "/home",
  templateUrl: "....",
  controller: function($scope,$state,authSvc) {
     if(authSvc.userIsLoggedIn()){
          $state.go('home.loggedin')
     }else{
          $state.go('home.public')
     }
  }
})


.state('home.public', {
  url: "",
  templateUrl: "....",
  controller: function($scope) {
     ...........
  }
})

.state('home.loggedin', {
  url: "",
  templateUrl: "....",
  controller: function($scope) {
     ...........
  }
})

Now in the controller of your base state (home) you can check if the user is logged in or not, and use $state.go() to load an appropriate state.

EDIT

As promised, a working plunk.

Mohammad Sepahvand
  • 17,364
  • 22
  • 81
  • 122
  • 1
    This doesn't seem to work. I think it has something to do with the similar URLs. If I comment out one of the sub states, it works. – JacobF Apr 29 '14 at 09:27
  • @jvannistelrooy, I've used this approach before, let me create a plunk. – Mohammad Sepahvand Apr 29 '14 at 09:47
  • 1
    Thanks, this works! Is it necessary to define empty url's in the substates. For me, it also works without them. – JacobF Apr 29 '14 at 10:53
  • Yea, that's not necessary at all, you can just leave them empty. – Mohammad Sepahvand Apr 29 '14 at 11:39
  • This working correct when tag "
    " exist in template for state "home".
    – centum Aug 22 '15 at 08:12
  • It doesnt' work for me, but the trick is the url: "", so I add that to the loggedout state, don't put it under home, and it worked – Pencilcheck Sep 12 '15 at 09:34
  • 1
    The parent and the childs has the same url, Your trick works just because the parent transact to the childs (home -> home.loggedin). If you transact directly to the child from another state (not 'home') it won't work correctly.. ui-router will call onExit of the child state. I couldn't find a solution to this.. even I can't declare a state as 'unactivable' by hitting the url – Paolo Sanchi Jan 08 '16 at 11:35
  • 1
    @PaoloSanchi you can solve that by making "home" state "abstract: true" – juancito Jul 01 '16 at 18:01
  • Using this approach there is issue when refreshing page from some reason both controllers are getting accessed, anyone knows anything about that ? – Sahbaz Jul 02 '18 at 16:46
0

I am not sure if two states can have the same url. What i can think can be a viable option would be to define a single state

$stateProvider.state('home', {
  templateUrl: function (stateParams){
    // Implement a logic that select what view from the server should be returned for logged in user and otherwise
    //return 'templateurl';
  }
})

I have not tried but it should work.

Chandermani
  • 42,589
  • 12
  • 85
  • 88
  • Thanks, that's what I tried to do, but it seems that I cannot pass my session or user model to `myApp.Config`, so I cannot build the right logic. – JacobF Apr 28 '14 at 14:59
  • Have you tried templateProvider which is fully injectable. You can try `
    – Chandermani Apr 28 '14 at 16:24