重新加载 AngularJS 控制器。

15

我是一个AngularJS的新手。

我的问题是,我有一个用户控制器来处理登录和注销。我还有另一个控制器来加载网站的头部菜单。

如果用户登录到网站上,我的isAuthenticated变量将设置为true。如果变量被设置为true,则应更改标题,所以我认为必须重新加载控制器以更改标题视图。

这里是我的HeaderController代码:

myapp.controller('HeaderController', ['$scope', '$location', '$window', 'AuthenticationService',  
    function HeaderController($scope, $location, $window, AuthenticationService) {
        $scope.isAuthenticated = AuthenticationService.isAuthenticated;

        if (AuthenticationService.isAuthenticated) {
            $scope.user.vorname = $window.sessionStorage.user.vorname;
        }
    }
]);

这是我的HeaderDirective代码:

myapp.directive('appHeader', function() {
  return {
    restrict: 'E',
    link: function(scope, element, attrs) {
      if (attrs.isauthenticated == 'false') {
        scope.headerUrl = 'views/header/index.html';
      } else {
        scope.headerUrl = 'views/header/isAuthenticated.html';
      }
    },
    template: '<div ng-include="headerUrl"></div>'
  }
});

我的 index.html:

<div ng-controller="HeaderController">
  <app-header isauthenticated="{{isAuthenticated}}"></app-header>
</div>

如果用户登录页面,我该如何重新加载控制器?

PS:请原谅我的发音不好。

2个回答

17
在用户通过身份验证后,添加以下代码:
// To refresh the page
$timeout(function () {
    // 0 ms delay to reload the page.
    $route.reload();
}, 0);

别忘了在你的控制器中包含$timeout$route

myapp.controller('HeaderController', ['$scope', '$location', '$window', 'AuthenticationService', '$timeout', '$route',
function HeaderController($scope, $location, $window, AuthenticationService, $timeout, $route)

谢谢。为了刷新一个动态表格,我使用了 $scope.$apply。在桌面版的 Chrome 浏览器上它运行得很好。然而,在 Android 的 webview 上它并没有自动刷新。您使用 $route 重新加载的技巧在 Android webview 4.4.2 上运行良好。 - nagu

13

无需重新加载控制器。Angular 足够聪明,能够在 $scope.isAuthenticated 状态更改时更改模板。

我在您的代码中看到一个问题,即一旦定义了 $scope.isAuthenticated,它就不再更改。我想当用户登录时,您设置了 AuthenticationService.isAuthenticated = true,但这种更改并没有传播到 $scope.isAuthenticated 属性,因为在 JavaScript 中,标量值按值而不是按引用复制。

有许多方法,例如将 AuthenticationService.isAuthenticated 属性从布尔值更改为函数:

angular.module('auth', [])
.factory('AuthenticationService', function () {
    // private state
    var isAuthenticated = false;

    // getter and setter
    var auth = function (state) {
        if (typeof state !== 'undefined') { isAuthenticated = state; }
        return isAuthenticated;
    };

    // expose getter-setter
    return { isAuthenticated: auth };
});

然后将该函数分配给$scope:

$scope.isAuthenticated = AuthenticationService.isAuthenticated;

然后在您的模板中使用该函数(不要忘记括号)

<app-header isauthenticated="{{ isAuthenticated() }}"></app-header>

编辑:

在编写一个plunk以展示一个可运行的例子时,我发现指令的链接函数只被调用了一次,因此根据这个stackoverflow线程中的解释,我修改了该指令来观察isauthenticated属性的变化:

angular.module('directives', [])
.directive('appHeader', function() {
  var bool = {
    'true': true,
    'false': false
  };

  return {
    restrict: 'E',
    link: function (scope, element, attrs) {
      attrs.$observe('isauthenticated', function (newValue, oldValue) {
        if (bool[newValue]) { scope.headerUrl = 'authenticated.html'; }
        else { scope.headerUrl = 'not-authenticated.html'; }
      });
    },
    template: '<div ng-include="headerUrl"></div>'
  }
});

这里是工作示例:http://plnkr.co/edit/Et6bFP?p=preview


谢谢,这就是我在寻找的东西。 - Rico Berger
不幸的是,这个答案对于每个搜索如何重新加载控制器的人来说都有点失败 :(. 是的,在这种情况下不需要,但还有其他用例(例如编写可以在接收事件后重新初始化UI部分的基础设施)。 - George Mauer
1
@GeorgeMauer,我也不明白为什么在你的用例中需要重新加载控制器。你能提供更多上下文吗?(或许最好打开一个新的SO问题,将其链接到此问题作为你需求的无效方法) - Pau Fracés

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