Dmitry Efimenko
Dmitry Efimenko

Reputation: 11203

Angular - Change css class on route state change based on $stateParams

I have a div in the layout page:

<div class="{{$root.containerClass}}">...</div>

There are two route states:

.state('controllerAction', {
    url: '/:controller/:action',
    templateUrl: function($stateParams) {
         return $stateParams.controller + '/' + $stateParams.action;
    },
    controllerProvider: function($stateParams) {
         return $stateParams.controller + $stateParams.action + 'Controller';
    },
    onEnter: function($rootScope, $stateParams) {
        $rootScope.containerId = $stateParams.controller.toLowerCase() + '-index';
    }
})
.state('controller', {
    url: '/:controller',
    templateUrl: function($stateParams) {
         return $stateParams.controller + '/index';
    },
    controllerProvider: function($stateParams) {
         return $stateParams.controller + 'Controller';
    },
    onEnter: function($rootScope, $stateParams) {
        $rootScope.containerId = $stateParams.controller.toLowerCase() + '-index';
    }
});

I'd like the class to be changed when the route changes using $stateParams. With the code above it does changes, but only to the containerClass of the previous route.

Any help is appreciated.

Upvotes: 6

Views: 12337

Answers (4)

Jan Ranostaj
Jan Ranostaj

Reputation: 146

It is allways better use directives for DOM manipulation and this is the case. In this example I'm using ui-router

Here is my code I'm using

Directive:

(function() {
'use strict';

angular.module( 'directives' ).directive( 'bodyClass', bodyClass );

bodyClass.$inject = [ '$rootScope'];

function bodyClass(  $rootScope  ) {
    return function( scope, elem, attr ) {

        $rootScope.$on( "$stateChangeSuccess", function( event, next, current    ) {
            var url = next.name.replace( /\./g, '-' );
            elem.attr( 'class', '' ).addClass( url );
        } );
    };
}
;
})();

HTML

<body body-class></body>

RESULT

So if you have URL like: app/welcome your body class will be :

<body class="app-welcome"></body>

Upvotes: 1

Ilan Frumer
Ilan Frumer

Reputation: 32357

Check my other answer: Route-Dependent CSS Page Transitions in AngularJS

I got it working with onEnter , plunker: http://plnkr.co/edit/LEMntLYosA2gIvNzw5gv?p=preview

I prefer doing something like this

Here is a plunker: http://plnkr.co/edit/3Wof05ck3lVLqgTBDOew?p=preview

Listen to a $stateChangeSuccess event:

States:

.state('home', {
    url: '/',
    templateUrl: '/account/index.html',
    controller: 'AccountLoginController',
    containerClass: 'account-index'
})
.state('book', {
    url: '/Book',
    templateUrl: '/book/index.html',
    controller: 'BookController',
    containerClass: 'book-index'
})

Run block:

app.run(function($rootScope){

    $rootScope.$on('$stateChangeSuccess',function(event, toState, toParams, fromState, fromParams){
        $rootScope.containerClass = toState.containerClass;
    });

});

Markup:

<div ng-class="{{containerClass}}">...</div>

Upvotes: 16

airtonix
airtonix

Reputation: 5154

You need :

  • a slugify filter
  • to associate $state to the $rootScope
  • modify your root template to include this variable.

First

Associate $state to $rootScope

angular.module("your-app", ['ui.router'])
        .run(['$rootScope',
              '$state',
              '$stateParams',
            function ($rootScope, $state, $stateParams) {
                $rootScope.$state = $state;
                $rootScope.$stateParams = $stateParams;
            }]);

Second

Include a slugify filter. something like this: http://paulsmith.github.io/angular-slugify/

Thirdly

<body id="{{$state.current.name|slugify}}"> ... </body>

Upvotes: 1

TruongSinh
TruongSinh

Reputation: 4856

Change

<div class="{{$root.containerClass}}">...</div>

to

<div ng-class="containerClass">...</div>

http://docs.angularjs.org/api/ng.directive:ngClass So, make use of ng-class directive, and when you want to access a scope variable (either local or root), just state the name, do not use $root

Upvotes: 0

Related Questions