Dynamic body class with Angular UI-Router

Issue

I’m trying to find an elegant way to have a custom dynamically class of the body tag that I can set easily from the ui-router configurations and if none is set, I can use a default option or none.

Example:

routes.js

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

Simple markup HTML

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

Scenario:

1 – Visiting the state login I should have the class of the body equals to auth

2 – Visiting the state register at this point it will have the same auth class

3 – Visiting the state profile the body will have the default class or none

How do you achieve that?

Solution

You can have a master AppController that controls this:

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

Inside your route defs:

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

See UI Router documentation for more on this data-attribute strategy.

Answered By – jmq

Answer Checked By – Pedro (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.