Angular - 根据用户的登录状态在相同的URL"/"下使用不同的模板

16

我想要两个不同的模板。一个是为未登录用户描述业务的登录页,另一个是为已登录用户显示仪表板页面。

我在这个 Stack Overflow 页面上看到了如何使用 UI-router 实现此目的的方法。我想知道如何使用 ngRoute 来做类似的事情的最佳实践?

下面的设置是这样的,"/frontdesk" 是仪表板,"/" 是登出用户的登录页。但是!无论用户是否在仪表板上或已退出登录并发送到登录页,我都希望 URL 保持不变!我不想要 "/frontdesk",我想要 IndexController 和 FrontdeskController 的 "/"。

以下是我的路由 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('/');
   }
})();

解决方案!

感谢大家的回答。

特别感谢 @ThibaudL 提供更好的解决方案。

这是我最终采用的方法:

在 Routes.js 中

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

主页.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();
  }
})();

现在,如果用户已通过身份验证,则会将模板切换到用户的仪表板。我为每个模板添加了一个带有ng-controller的新div,以便每个模板都有它们自己独立的控制器。

8个回答

8

添加另一个属性,像这样 isGuest: true

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

并且。
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();
   }
 });
});

你可以编写自己的服务SessionSession.isAuthenticated()//基于用户是访客还是已登录,返回truefalse

我知道这很老,但是这适用于ngRoute还是ui-router? - Anthony

4
您可以使用 resolve 属性来检查用户是否已登录。
$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");
            }
        }
    }
    })

4

将$locationProvider与$routeProvider一起使用

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

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

注意它的模板不是templateUrl,而是template。同时,模板应该是“”,而不仅仅是“”。接着,在你的index控制器中,
.controller('IndexController', function($scope, $route, $routeParams, $location) {
 if ($scope.user.loggedIn) $location.path('/:user'); else $location.path('/:visitor');})

请注意,路径与 '/' 相同,但对于已登录用户为 /:user,对于匿名用户为 /:visitor。

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; 
   });
  }
})();

谢谢,我搞定了!我修改了你的答案以展示我是怎么让它正常工作的。 - Austin Perez

0

有几件事情可以做,最简单的是,在FrontdeskController的开头检查登录状态,如果未登录,则导航到主页。

您还可以在路由上添加变量,并像以前的答案一样进行检查。

还有更极端的情况,我认为这是非常糟糕的做法,比如编写双状态模板页面,但是再次强调,这不是一个好方法。

希望这可以帮助到您。


0

对于templateUrl,你可以使用如下的函数:

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

你可以阅读$routeProvider

templateUrl – {string=|function()=} – 路径或返回应该被 ngView 使用的 HTML 模板的函数。

如果 templateUrl 是一个函数,它将被以下参数调用:

{Array.< Object >} - 通过应用当前路由从当前 $location.path() 中提取的路由参数


0

这是一个完整的解决方案:

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);
            }
        }
    });
});

0

第一次尝试

.

在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';
   });
  }
})();

现在,如果用户已通过身份验证,它只需将模板切换到用户的仪表板。我为每个模板添加了一个带有ng-controller的新div,以便每个模板都有其单独的控制器。


this is horrible, please use one of the provided answers instead - terafor
这真的不是一个好的做法,看看提供的答案,使用on routeChangeStart。 - ThibaudL
@ThibaudL 感谢您的评论,但您能告诉我为什么这不是一个好的做法吗?这会带来安全威胁吗?我正在寻找最佳实践,并且非常愿意听取最佳解决方案。此外,我想让每个模板保持相同的URL(www.mybusiness.com/)。 - Austin Perez
不,这更多是性能问题,因为如果你知道只需要在特定时刻(这里是routeChangeStart)查看它,那么这个观察者将被频繁调用,最好监听该唯一事件。 - ThibaudL
@ThibaudL 好的,我明白你在说什么,你提出的观点很好。但是从提供的答案中,我真的不明白如何使用routeChangeStart,如果我只是使用不同的模板相同的URL。我不知道我的问题是否清楚,但我不希望“/frontdesk”成为用户登录后的URL。我希望URL无论用户是否登录都保持为“www.mybusiness.com/”。 - Austin Perez
1
我明白你的意思了,那些答案对你来说不太好。我会给你写另一个答案。 - ThibaudL

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接