Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 465
Dmitry Efimenko Avatar asked Jan 26 '14 10:01

Dmitry Efimenko


3 Answers

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>
like image 103
Ilan Frumer Avatar answered Nov 12 '22 03:11

Ilan Frumer


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>
like image 40
airtonix Avatar answered Nov 12 '22 01:11

airtonix


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>
like image 1
Jan Ranostaj Avatar answered Nov 12 '22 03:11

Jan Ranostaj