Angular - same Url "/" but with different templates based on user's logged in status
Asked Answered
M

8

16

I am trying to have two different templates. One that is the landing page for logged out users describing about the business and the other dashboard page for if a user is logged in.

I read on this other stack on how to do this with UI-router. I would like to know the best practice to do something similar like this using ngRoute?

The way it is setup below, is that "/frontdesk" is the dashboard and "/" is the landing page for logged out users. BUT! I want the URL to be the same for whether the user is on the dashboard or is logged out and sent to the landing page! I do not want "/frontdesk", I want "/" for IndexController and FrontdeskController.

Here is my routing JS.

(function () {
      'use strict';

    angular
      .module('resonanceinn.routes')
      .config(config);

    config.$inject = ['$routeProvider'];

    function config($routeProvider) {
      $routeProvider
        .when('/', { // This is the landing Page
            controller: 'IndexController',
            controllerAs: 'vm',
            templateUrl: '/static/javascripts/layout/index.html'
        })
        .when('/frontdesk', { //This is logged in user that I want to become '/' as well
            controller: 'FrontdeskController',
            controllerAs: 'vm',
            templateUrl: '/static/javascripts/frontdesk/frontdesk.html'
        })
        .when('/register', {
            controller: 'RegisterController', 
            controllerAs: 'vm',
            templateUrl: '/static/javascripts/authentication/register.html'
        })
        .when('/login', {
            controller: 'LoginController',
            controllerAs: 'vm',
            templateUrl: '/static/javascripts/authentication/login.html '
        })
        .when('/:username', {
            controller: 'ProfileController',
            controllerAs: 'vm',
            templateUrl: '/static/javascripts/profiles/profile.html'
        })
        .when('/:username/settings', {
            controller: 'ProfileSettingsController',
            controllerAs: 'vm',
            templateUrl: '/static/javascripts/profiles/settings.html'
     }).otherwise('/');
   }
})();

Solution!

Thank you everyone for your answers.

Thanks to @ThibaudL for the better solution.

This is how I ended up doing it:

In Routes.js

 .when('/', {
        controller: 'MainController',
        controllerAs: 'vm',
        templateUrl: '/static/javascripts/layout/Main.html'

Main.html

<div ng-include="" src="'/static/javascripts/layout/index.html'" ng-if="auth"></div>
<div ng-include="" src="'/static/javascripts/frontdesk/frontdesk.html'" ng-if="!auth"></div>

MainController.js

(function () {
  'use strict';

  angular
    .module('resonanceinn.layout.controllers')
    .controller('StartController', StartController);

  StartController.$inject = ['$scope', '$route', '$routeParams', '$location', 'Authentication'];

  function StartController($scope, $route, $routeParams, $location, Authentication) {

      $scope.auth = Authentication.isAuthenticated();
  }
})();

So now if the user is Authenticated, it just switches the templates to the users dashboard. I added a new div with ng-controller to each template so that each template has their separate controllers.

Magel answered 8/7, 2015 at 17:53 Comment(0)
B
3

What I would do is :

Main.html

<div ng-include="" src="'/static/javascripts/layout/index.html'" ng-if="auth"></div>

MainController.js

(function () {
  'use strict';

  angular
    .module('App.layout.controllers')
    .controller('MainController', MainController);

  MainController.$inject = ['$scope', '$route', '$routeParams', '$location', 'Authentication'];

  function MainController($scope, $route, $routeParams, $location, Authentication) { 

      $scope.auth = Authentication; 
   });
  }
})();
Bantling answered 21/8, 2015 at 14:59 Comment(1)
Thank you, I got it to work! I corrected your answer to show How I made it work.Magel
F
8

Add another property, like this isGuest: true

.when('/', {
        controller: 'IndexController',
        controllerAs: 'vm',
        templateUrl: '/static/javascripts/layout/index.html',
        isGuest: true
})
 .... ...............

and

app.run(function($rootScope, $state, Session) {
 $rootScope.$on("$stateChangeStart", function(event, toState, toParams, fromState, fromParams) {
  if (toState.isGuest == true && Session.isAuthenticated()) {
   // User isn’t authenticated
   // do redirection to guest user
    event.preventDefault();
  }

  if (toState.authentication == true && !Session.isAuthenticated()) {
    // do redirection to loggedin user 
    event.preventDefault();
   }
 });
});

You can write your own service Session,

Session.isAuthenticated() // returns true or false,based on whether user is guest or loggedin

Flaxman answered 8/7, 2015 at 18:4 Comment(1)
I know this is old, but does this apply to ngRoute or ui-router?Clangor
D
4

You can use resolve property to check if user is logged in.

$routeProvider
    .when('/somepage' ,{
    templateUrl: "templates/template.html",
    resolve:{
        "check":function($location){  
            if('Your Condition'){
                //Do something
            }else{
                $location.path('/');    //redirect user to home.
                alert("You don't have access here");
            }
        }
    }
    })
Deste answered 19/8, 2015 at 13:22 Comment(0)
C
4

Inject $locationProvider with your $routeProvider

config.$inject = ['$locationProvider'];

then

function config($routeProvider, $locationProvider ) {
  $routeProvider
    .when('/', {
        controller: 'IndexController',
        controllerAs: 'vm',
        template: " "
    })

...

note its template not templateUrl, also the template is " " note just ""

then in your index controller

.controller('IndexController', function($scope, $route, $routeParams, $location) {
 if ($scope.user.loggedIn) $location.path('/:user'); else $location.path('/:visitor');})

note that same path as '/' but /:user for loggedIn users and /:visitor for anonymous

Commissariat answered 20/8, 2015 at 21:1 Comment(0)
B
3

What I would do is :

Main.html

<div ng-include="" src="'/static/javascripts/layout/index.html'" ng-if="auth"></div>

MainController.js

(function () {
  'use strict';

  angular
    .module('App.layout.controllers')
    .controller('MainController', MainController);

  MainController.$inject = ['$scope', '$route', '$routeParams', '$location', 'Authentication'];

  function MainController($scope, $route, $routeParams, $location, Authentication) { 

      $scope.auth = Authentication; 
   });
  }
})();
Bantling answered 21/8, 2015 at 14:59 Comment(1)
Thank you, I got it to work! I corrected your answer to show How I made it work.Magel
B
0

there are a couple of things you can do, the simplest being, checking for a logged in status in the beginning of your FrontdeskController and navigate to the homepage if not logged in.

you can also add variables on the route and check for them like in the previous answer.

there are more extreme cases you can do, which I find to be very bad practice, like writing a double state template page, but again, that's not a good thing to do.

I hope this helped

Barclay answered 16/8, 2015 at 9:45 Comment(0)
M
0

For templateUrl, you can use a function like,

templateUrl : function(parameter) {
   if(loggedin) {
       return '/static/javascripts/layout/index.html';
   } else {
       return 'logged out page';
   }
}

You can read $routeProvider,

templateUrl – {string=|function()=} – path or function that returns a path to an html template that should be used by ngView.

If templateUrl is a function, it will be called with the following parameters:

{Array.< Object >} - route parameters extracted from the current $location.path() by applying the current route

Merriment answered 20/8, 2015 at 9:38 Comment(0)
S
0

Here's a complete solution:

var app = angular.module('app', ['ngRoute']);

app.config(function($routeProvider) {
    $routeProvider
        .when('/', {
            controller: 'IndexController',
            controllerAs: 'vm',
            templateUrl: '/static/javascripts/layout/index.html'
        })
        .when('/frontdesk', {
            controller: 'FrontdeskController',
            controllerAs: 'vm',
            templateUrl: '/static/javascripts/frontdesk/frontdesk.html',
            requireLogin: true
        });
});

app.factory('authService', function () {
    var service = {
        isAuthenticated: false,
        loginPageUrl: '/login'
    };

    return service;
});

app.run(function ($rootScope, $location, authService) {
    $rootScope.$on('$routeChangeStart', function (event, next) {
        if (angular.isDefined(next) && next !== null && angular.isDefined(next.requireLogin)) {
            if (next.requireLogin === true && !authService.isAuthenticated) {
                event.preventDefault();
                $location.path(authService.loginPageUrl);
            }
        }
    });
});
Skat answered 20/8, 2015 at 22:25 Comment(0)
M
0

First Attempt

.

In Routes.js

 .when('/', {
        controller: 'MainController',
        controllerAs: 'vm',
        templateUrl: '/static/javascripts/layout/Main.html'

Main.html

<div ng-include="mainTemplate"></div>

MainController.js

(function () {
  'use strict';

  angular
    .module('App.layout.controllers')
    .controller('MainController', MainController);

  MainController.$inject = ['$scope', '$route', '$routeParams', '$location', 'Authentication'];

  function MainController($scope, $route, $routeParams, $location, Authentication) { 

      $scope.$watch(function($scope) {
          return $scope.mainTemplate = Authentication.isAuthenticated() ? '/static/javascripts/layout/index.html' : '/static/javascripts/frontdesk/frontdesk.html';
   });
  }
})();

So now if the user is Authenticated, it just switches the templates to the users dashboard. I added a new div with ng-controller to each template so that each template has their separate controllers.

Magel answered 21/8, 2015 at 1:5 Comment(6)
this is horrible, please use one of the provided answers insteadDeste
That's really not a good way of doing it, look at the provided answers using the on routeChangeStartBantling
@Bantling thanks for your comment but can you tell me why this is not a good way of doing it? Is this a security threat? I am looking for the best practice and am all ears for the best solution. Also, I want to keep the URL (www.mybusiness.com/) the same for each template.Magel
No it's more of a performance issue, because this watcher will be called way to often, if you know you only require to look a this at a certain moment (here it's the routeChangeStart) it's better to listen for that unique eventBantling
@Bantling Ok I see what you are talking about and that is a good point that you bring up. I really don't understand(from the answers provided) how routeChangeStart can be used if I am using the the same URL just with different templates. I don't know if my question made it clear, but I DO NOT want "/frontdesk" to be the url when the user is logged in. I want the URL to stay "www.mybusiness.com/" if the user is logged in or not.Magel
I see what you meant then, The answers are not good for you then. I'll write you another answerBantling

© 2022 - 2024 — McMap. All rights reserved.