Classe de corps dynamique avec Angular UI-Router

J'essaie de trouver une façon élégante d'avoir une classe dynamique personnalisée de la balise de corps que je peux régler facilement à partir des ui-router configurations et si aucune n'est définie, je peux utiliser une option par défaut ou aucune.

Exemple:

Routes.js

 $stateProvider .state('login', { url: "/login", template: 'Login' }) .state('register', { url: "/register", template: 'Register' }). .state('profile', { url: "/profile", template: 'Profile' });; 

Marquage simplifié HTML

 <html> <body class=""> <!-- Dynamically class to change --> <div ui-view></div> </body> </html> 

Scénario:

1 – Visiter l' state connexion Je devrais que la classe du corps soit égale à auth

2 – En visitant le registre d' state à ce stade, il aura la même classe d' auth

3 – En visitant le profil d' state , le corps aura la classe par défaut ou aucun

Comment parviens-tu cela?

Vous pouvez avoir un AppController principal qui contrôle ceci:

 <html ng-app="app" ng-controller="AppController as appController"> ... <body class="{{ appController.bodyClasses }}"> 

Inside AppController:

 var vm = this; vm.bodyClasses = 'default'; // this'll be called on every state change in the app $scope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams){ if (angular.isDefined(toState.data.bodyClasses)) { vm.bodyClasses = toState.data.bodyClasses; return; } vm.bodyClasses = 'default'; }); 

À l'intérieur de votre parcours:

  .state('register', { url: "/register", template: 'Register', data: { bodyClasses: 'auth' } }); 

Consultez la documentation de UI Router pour en savoir plus sur cette stratégie d'attributs de données.

Voici une approche similaire à laquelle @ jmq utilise les données d'état, mais implémentée comme une directive au lieu d'un contrôleur. (La bonne chose à propos de la directive est que vous pouvez appliquer cela à des éléments arbitraires)

Exemple de balisage

 <body ng-app="app" route-css-classnames> 

Routes Config (routes.js)

 $stateProvider .state('login', { url: "/login", template: 'Login', data : { cssClassnames : 'auth' } }) .state('register', { url: "/register", template: 'Register', data : { cssClassnames : 'auth' } }). .state('profile', { url: "/profile", template: 'Profile' }); 

Directive (routeCssClassnames.js)

 (function () { 'use strict'; angular.module('shared').directive('routeCssClassnames', routeCssClassnames); function routeCssClassnames($rootScope) { return { restrict: 'A', scope: {}, link: function (scope, elem, attr, ctrl) { $rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) { var fromClassnames = angular.isDefined(fromState.data) && angular.isDefined(fromState.data.cssClassnames) ? fromState.data.cssClassnames : null; var toClassnames = angular.isDefined(toState.data) && angular.isDefined(toState.data.cssClassnames) ? toState.data.cssClassnames : null; // don't do anything if they are the same if (fromClassnames != toClassnames) { if (fromClassnames) { elem.removeClass(fromClassnames); } if (toClassnames) { elem.addClass(toClassnames); } } }); } } } }()); 

Vous pouvez également l'appliquer sur votre étiquette de corps ou partout où vous en avez besoin.

 ng-class="$state.current.name"