Why ng-class is not applied as per the current state of ui router?

560 views Asked by At

My application has two different views (page1 and page2), which has been configured with ui-router's stateProvider. I want to apply a css on the body based on what page I am looking at. If I am looking at page1 I want to apply class1 to the body of the page and class2 for page2.

To achieve this I am using the ng-class directive of the angularjs. The value of the ng-class directive is being set as per the current state of the ui-router.

Here is the example code for it, the problem is that the expression inside the ng-class doesn't get evaluated, so my css doesn't get applied.

Can anyone point me what I am doing wrong ?

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.4.2/angular-ui-router.min.js"></script>

    <style media="screen">

    h2 {
      margin: 5px 5px 5px 5px;
    }
    body {
      display: flex;
      flex-direction: column;
    }
    .class1 {
      align-items: flex-start;
    }
    .class2 {
      align-items: center;
    }
    </style>
  </head>

  <body ng-app="graceApp" ng-class="$state.current.data.bodyClass">

    <div ui-view style="display: flex"></div>

    <script>
    angular
      .module('graceApp', [
        'ui.router'
      ])
      .config(function ($stateProvider, $urlRouterProvider) {
        $stateProvider
          .state('page1', {
            url: '/page1',
            template: '<h2>This is page1</h2> <h2>Item1</h2> <h2>Item2</h2>',
            data: {
              bodyClass: 'class1'
            }
          })
          .state('page2', {
            url: '/page2',
            template: '<h2>This is page2</h2> <h2>Item1</h2> <h2>Item2</h2>',
            data: {
              bodyClass: 'class2'
            }
          });
        $urlRouterProvider.otherwise('/page1');
      });
    </script>
</body>
</html>
3

There are 3 answers

4
Sadok Mtir On BEST ANSWER

The $state service is not available in HTML. You just have access in the html to the variables set in the scope so a quick fix would be to set the state in the rootScope then you could access it in the HTML.

$rootScope.$state = $state;
3
mbeso On

I'm not sure whether $state service is accessible in HTML like this. Did you consider to create some function in your controller that will return $state.current.data.bodyClass and then, you link that function into ng-class

function getClass() {
    return $state.current.data.bodyClass;
}

HTML:

<body ng-app="graceApp" ng-class="getClass()">

If you are using controllerAs pattern, make sure you make this function public and use it inside HTML with controller alias.

3
Gaurav Kumar Singh On

You can't access $state in html directly, so you need to define another scope variable in controller like

<!doctype html>
<html ng-app="graceApp">

<head>
    <meta charset="utf-8">
    <title></title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.4.2/angular-ui-router.min.js"></script>
    <style media="screen">
    .class1 {
        background-color: red;
    }

    .class2 {
        background-color: green;
    }
    </style>
</head>
<body ng-controller="mainController" ng-class="bodyClass">
    <div ui-view></div>
    <script>
    angular.module('graceApp', ['ui.router']).config(function($stateProvider, $urlRouterProvider) {
        $stateProvider
            .state('page1', {
                url: '/page1',
                template: '<h2>This is page1</h2> <h2>Item1</h2> <h2>Item2</h2>',
                data: {
                    bodyClass: 'class1'
                }
            })
            .state('page2', {
                url: '/page2',
                template: '<h2>This is page2</h2> <h2>Item1</h2> <h2>Item2</h2>',
                data: {
                    bodyClass: 'class2'
                }
            });
        $urlRouterProvider.otherwise('/page1');
    });

    angular.module("graceApp").controller("mainController", function($rootScope, $scope) {
        $rootScope.$on("$stateChangeSuccess", function(event, current, params) {
            console.log(current.data.bodyClass);
            $scope.bodyClass = current.data.bodyClass;
        });
    });
    </script>
</body>
</html>