web-dev-qa-db-fra.com

AngularJS Modification de la classe <body> à l'aide d'une variable globale

Je viens de créer une application angularJS.

Voici mon 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.
}]);

J'ai login.html, register.html et Forgotpassword.html, home.html. Chacun a des contrôleurs séparés dans des fichiers séparés. 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";
        }
    }
});

De même, j'ai des méthodes de publication dans d'autres contrôleurs.

Ce que je veux, c'est que lorsque la vue est une connexion ou un enregistrement ou un mot de passe oublié, la classe de corps doit être "login-layout". Donc, dans le corps, je mets class="{{bodylayout}} ". Je sais qu'en utilisant des variables globales, la valeur peut être définie. Mais je ne sais pas comment.

Dans app.js j'ai essayé ceci

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

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

    });

Mais je ne sais pas comment l'utiliser.

17
Shiju K Babu

Vous pouvez créer des variables globales de deux manières

En utilisant $rootScope vous pouvez faire quelque chose comme dans votre LoginController contrôleur

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

   //others code 
}

Utilisation de service

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

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

});

Utilisez ce service dans votre contrôleur

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

       //others code 
    }

À quoi ressemble votre HTML

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

Remarque dans ce cas, vous devez définir bodylayout dans chaque contrôleur sinon il utilise l'ancienne valeur

19
Reza

Essayez d'utiliser $ rootScope:

$rootScope.bodyClass = 'login-layout';

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

Vous pouvez gérer cela dans les contrôleurs individuels, ou peut-être dans votre app.js en écoutant 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;
    }
});
10
imcg

Vous pouvez créer une directive <body> Qui a ajouter et supprimer des événements de classe qui peuvent être déclenchés dans votre application.

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

Dans votre bloc app.jsconfig, vous pouvez définir le <body>class à votre guise avec $emit

## Add class
$rootScope.$emit('body:class:add', 'login-layout')

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

il utilise simplement le angular jqLite addClass() et removeClass() et ne vous oblige pas non plus à puiser dans $element en utilisant le directive link fonction qui a déjà un accès dom à l'élément.

Même sans $rootScope, Vous pouvez l'appeler dans vos contrôleurs avec $scope.$emit('body:class:add', name).

8
twmulloy

Je ne suis pas trop sûr que les réponses suggérées fonctionnent pour Angular 1.4x mais je pense que j'ai une solution plus facile.

Vous pouvez facilement ajouter une propriété activeTab à vos itinéraires comme ceci:

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

Ensuite, dans votre Controller, ajoutez l'objet $ route à votre $ scope:

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

Et utilisez ng-class sur votre balise body:

<body ng-class="{'register-class' : $route.current.activeTab == 'register' }">
</body>

De cette façon, vous pouvez définir dynamiquement une classe sur votre balise body lorsque vous changez de route. J'espère que cela aide quelqu'un!

1
Yeysides