Angularjs:用户登录时使用不同模板的redraw指令

时间:2013-07-26 12:28:17

标签: angularjs angularjs-directive

在我们的总体布局中,我们有一个侧边栏,其中包含一些用户详细信息,如名称和缩略图。还有一些不同的东西。

我们有想法加载带有指令的侧栏,其中有2个模板,1个登录时和1个登出时。

显示并不显示用户详细信息。

但是,我们有一个名为sidebar的指令,使用2中的任何一个

App.directive('sidebar',['UserService','$ compile',function(User,$ compile){

var getTemplate = function() {
    console.warn(User.isLogged);
    var templateUrl = "#sidebar" + ((User.isLogged) ? '_loggedin' : '') + "_template";
    console.log('requesting template: [%s]', templateUrl);
    return $(templateUrl).html();
};

return {
    restrict: 'A',
    link: function link(scope, element, attrs) {
        var tmpl = getTemplate();
        element.html(tmpl);
        element.replaceWith($compile(element.html())(scope));
    },
    template: getTemplate()
};

}]);

我们在服务中加载用户详细信息

App.factory('UserService', [function userService() {
var User = {
    isLogged: false,
    username: ''
};
return User;
}]);

登录表单接受此UserService作为依赖项,并将其isLogged设置为true

但是当isLogged发生变化时,如何让指令重新标注侧边栏?

我们这样做是正确的吗?

1 个答案:

答案 0 :(得分:1)

有一个阶段称为编译阶段,其中有角度

  

遍历DOM以识别所有已注册的指令   模板。对于每个指令,它然后根据指令转换DOM   规则(模板,替换,转换等),并调用compilefunction   如果它存在结果是编译的模板函数,它将调用链接   从所有指令中收集的函数。

基本上,你不能有条件地加载模板 - 它会编译你给它的第一个模板。如果要动态渲染视图,可以在模板中使用两个带有ng-show指令的div:

<div ng-show="user.isLogged">// logged in content</div>
<div ng-show="!user.isLogged">// logged out content</div>

你可能认为你需要在你的指令中注入一个工厂 - 我刚试过这个并且它不起作用!我相信这是因为指令只能与作用域链上的指令建立单向和双向绑定。考虑到这一点,我将用户对象带入了应用程序范围:

App.controller("AppCtrl", function($rootScope, UserService) {
  $rootScope.user = UserService;
})

然后使用指令中的开放范围:

app.directive("sidebar", function() {

  return {
    restrict: "A",
    template: '<div>' +
      '<div ng-show="user.isLogged">Logged In</div>' +
      '<div ng-show="!user.isLogged">Logged Out</div></div>',
  }

})

此处的用户对象是通过范围链接找到的。因为该指令没有隔离范围(我没有声明范围属性),所以它通过范围链找到它 - 直到根范围。从某种意义上说,这当然是一种“全球性”,很容易被隐藏起来:

$scope.user = somethingElse

不是最漂亮的解决方案,但它可以胜任。

您还可以在链接函数中有条件地操作DOM,或者更好的是 - 将这种逻辑加载到使用嵌套模板并解析的路由器上。