Catfish
Catfish

Reputation: 19284

AngularJS dynamically set class on <html> tag based on route

I'm not sure the best way to approach this.

I want to dynamically set a class on my /login route so that my login page can have a large background image.

What is the best way to approach this?

Here's my current code:

<!DOCTYPE html>
<html class="SOME_DYNAMIC_CLASS_HERE_BASED_ON_ROUTE">
...
</html>
<body ng-app="myApp">
  <div ng-view=""></div>
</body>

angular.module('myApp', ['ngRoute']).config(function ($routeProvider) {
    $routeProvider
      .when('/login', {
        templateUrl: 'login.html',
        controller: 'LoginCtrl'
        })
      .when('/', {
        templateUrl: 'dashboard.html',
        controller: 'DashboardCtrl'
      })

Upvotes: 6

Views: 2651

Answers (3)

iamdash
iamdash

Reputation: 449

I know this is an old thread, but I came across it looking for some pointers. I have gone for the following method which feels more "Angular". Note, it is using a controllerAs-based directive:

ngModule.directive('routeClass', routeClass);

function routeClass($state, $log) {

    function controllerFn($scope) {

        var routeClass = this;

        $scope.$on('$stateChangeSuccess', function(){
            // I have a different class name assignment as the 
            // setup of my states is relatively complex, 
            // but this should demonstrate the idea
            routeClass.current = 'page-' + $state.current.name;
        });
    }

    return {
        controller: controllerFn,
        controllerAs: 'routeClass',
        restrict: 'A'
    };
}

And it is used as follows in index.html:

<body ng-app="app" route-class ng-class="{{routeClass.current}}">

Upvotes: 0

ryeballar
ryeballar

Reputation: 30088

You must have your ng-app attached in the <html> element, to have any sort of connection between angular and the view. Since you want something to change base on the current route of your application, then why not use those routes as a reference for your configuration, e.g. the $routeProvider configuration. Attach all your configuration, including configuration from classes to styles or any other configuration within the route object. You can then create a directive that listens to route changes via $routeChangeSuccess and then get the current route and other properties using the $route object defined as the second parameter of the $routeChangeSuccess listener, once you have those properties, you can do whatever you want with it e.g. append a class to that directive element.

DEMO

Javascript

Configuration

  .config(function ($routeProvider) {
    $routeProvider
      .when('/dashboard', {
        templateUrl: 'dashboard.html',
        'class': 'bg-dashboard'
      })
      .when('/login', {
        templateUrl: 'login.html',
        'class': 'bg-login'
      })
      .otherwise({redirectTo: '/login'});
  });

Directive

  .directive('classRoute', function($rootScope, $route) {

    return function(scope, elem, attr) {
      var previous = '';
      $rootScope.$on('$routeChangeSuccess', function(event, currentRoute) {
        var route = currentRoute.$$route;
        if(route) {

          var cls = route['class'];

          if(previous) {
            attr.$removeClass(previous);
          }

          if(cls) {
            previous = cls;
            attr.$addClass(cls);
          }
        }
      });
    };

  });

HTML

<html ng-app="myApp" class-route>...</html>

Upvotes: 7

New Dev
New Dev

Reputation: 49590

Using a directive is one way to go.

.directive("routeClass", function($location, $parse) {
    var mapping = {};
    return {
      restrict: "A",
      scope: {},
      link: function(scope, element, attrs) {
        mapping = $parse(attrs["routeClass"])(scope);
        // do something with mapping and $location or $routeParams
      }
    }
  });

<any route-class="{'/': 'default', '/Book': 'book'}" />

Another - is to set it via $rootScope.

Upvotes: 0

Related Questions