AngularJS使用全局变量更改<body>类

17

我刚刚创建了一个AngularJS应用程序。

这是我的index.html文件。

<html ng-app="MyApp">
  <head>
    <!-- CSS files import -->
  </head>
  <body class="{{bodylayout}}">
    <div ng-view></div>
  </body>
  <--! JS imports 
   aungular.js
   app.js
   login.js
   register.js
   -->
</html>

app.js

'use strict';
//Define Routing for app
angular.module('myApp', []).config(['$routeProvider', '$locationProvider',
  function($routeProvider,$locationProvider) {
    $routeProvider
    .when('/login', {
        templateUrl: 'login.html',
        controller: 'LoginController'
    })
    .when('/register', {
        templateUrl: 'register.html',
        controller: 'RegisterController'
      })
    .when('/forgotPassword', {
        templateUrl: 'forgotpassword.html',
        controller: 'forgotController'
      })
   .when('/home', {
       templateUrl: 'views/home.html',
    })
    .otherwise({
       redirectTo: '/login'
    });
//    $locationProvider.html5Mode(true); //Remove the '#' from URL.
}]);

我有登录页面login.html、注册页面register.html和忘记密码页面forgotpassword.html,还有主页home.html。每一个页面都有独立的控制器,存在不同的文件中,分别为login.js、register.js、forgot.js和home.js。

login.js

'use strict';

angular.module('myApp').controller('LoginController', function($scope, $location, $window) {
    $scope.user = {};
    $scope.loginUser=function()
    {
        var username=$scope.user.name;
        var password=$scope.user.password;
        if(username=="admin" && password=="admin123")
        {
            $location.path( "/home" );  
        }
        else
        {
            $scope.message="Error";
            $scope.messagecolor="alert alert-danger";
        }
    }
});
同样地,我在其他控制器中有提交方法。
我的希望是,当视图为登录、注册或忘记密码时,主体类应为“login-layout”。因此,在主体中我放置了“class = {{bodylayout}}”。我知道可以使用全局变量来设置值。但我不知道如何设置。
在app.js中,我尝试过这个:
angular.module('myApp').factory("myService", function(){

      return {
        sharedObject: { data: 'login-layout' }
      }; 

    });

但是不知道如何使用它。

4个回答

19

你可以通过两种方式创建全局变量

使用 $rootScope ,你可以在你的 LoginController 控制器中实现类似以下的功能

angular.module('myApp').controller('LoginController', function($scope, $location, $window, $rootScope) {
   $scope.user = {};
   $rootScope.bodylayout = 'login-layout';

   //others code 
}

使用service

angular.module('myApp').factory("myService", function(){

      return {
        sharedObject: { data: 'login-layout' }
      }; 

});

在您的控制器中使用此服务

angular.module('myApp').controller('LoginController', function($scope, $location, $window, myService) {
       $scope.user = {};
       $rootScope.bodylayout = myService.sharedObject.data; // get data from service

       //others code 
    }

当你的 HTML 看起来像这样时

<body class="{{bodylayout}}">

注意:在这种情况下,您需要在每个控制器中设置bodylayout,否则它会使用旧值。


谢谢。如果是其他控制器,如何设置为其他或空白? - Coder
在其他控制器中,您可以设置 $rootScope.bodylayout = ''$rootScope.bodylayout = '其他值' - Tasnim Reza
有了服务,怎样呢?因为我们正在使用$rootScope.bodylayout = myService.sharedObject.data;,没有从控制器传递任何值。 而且我想在每个控制器中更改页面的标题。 - Coder
在您的服务中设置不同的值,例如 sharedObject: { data: 'login-layout', data2: 'another-layout' },然后在另一个控制器中使用 $rootScope.bodylayout = myService.sharedObject.data2 - Tasnim Reza
从控制器中我们不能设置吗?在服务中创建一个方法并从控制器传递值? - Coder

11

尝试使用$rootScope:

$rootScope.bodyClass = 'login-layout';

<body class="{{$root.bodyClass}}">

你可以在各个控制器中处理这个问题,或者在app.js中通过监听routeChangeSuccess来处理:

$rootScope.$on('$routeChangeSuccess', function (event, currentRoute) {
    switch(currentRoute.templateUrl) {
        case 'login.html':
        case 'register.html':
        case 'forgotpassword.html':
            $rootScope.bodyClass = 'login-layout';
            break;
        default:
            $rootScope.bodyClass = '';
            break;
    }
});

在哪里使用?在哪个JS文件中? - Coder
更加简洁的解决方案,谢谢!虽然我仍然会选择使用服务。 - Spock
由于此处在 $rootScope 中,您可以在视图中使用 <body class="{{bodyClass}}"> 简单地引用它。 - skilleo

8
您可以创建一个包含添加和删除类事件的 <body> 指令,该指令可以在整个应用程序中触发。
angular.module('myApp').directive('body', [function(){
  return {
    restrict: 'E',
    link: function(scope, element, attrs) {
      scope.$on('body:class:add', function(e, name){
        element.addClass(name);
      };
      scope.$on('body:class:remove', function(e, name){
        element.removeClass(name);
      };
      return;
    }
  };
}]);

在你的app.js config块中,你可以使用$emit<body>标签的class设置为任何你想要的内容。
## Add class
$rootScope.$emit('body:class:add', 'login-layout')

## Remove class
$rootScope.$emit('body:class:remove', 'login-layout')

这段代码简单地使用了Angular jqLite中的addClass()removeClass()方法,而且不需要通过指令的link函数来获取元素的DOM访问权限。

即使没有$rootScope,你也可以在控制器中调用它,只需要使用$scope.$emit('body:class:add', name)


1

我不太确定建议的答案是否适用于Angular 1.4x,但我认为我有一个更简单的解决方案。

你可以像这样轻松地将activeTab属性添加到你的路由中:

.when('/register', {
        templateUrl: 'register.html',
        controller: 'RegisterController',
        activeTab: 'register'
      })

然后在你的控制器中将$route对象添加到$scope中:

.controller('RegisterController', ['$scope', '$route', function($scope, $route){
     $scope.$route = $route;
}])

在你的body标签上使用ng-class:
<body ng-class="{'register-class' : $route.current.activeTab == 'register' }">
</body>

这样,当你切换路由时,你可以动态地在你的body标签上设置一个类。希望这能帮助到某些人!

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