Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Different body background for different UI-Router states

In a simplified scenario, I have two UI-Router states and want different body background colors for them.

Ideally, I would thus like to do the following:

<body ng-class="background" ui-view>
</body>

and then in the controller for the states set the background classes (which might be dynamic, meaning: calculated in the controller):

stateHelperProvider
    .state({
        name: 'a',
        url: '/a',
        templateUrl: 'views/a.html',
        controller: function ($scope) {
            $scope.background = 'bg1';
        }
    })
    .state({
        name: 'b',
        url: '/b',
        templateUrl: 'views/b.html',
        controller: function ($scope) {
            $scope.background = 'bg2';
        }
    });

But putting the ui-view attribute on the body deletes it. So I have to put the ui-view attribute on a div inside the body.

<body>
    <div ui-view></div>
</body>

How can I now control the body background?

I am aware of various hacks (e.g. access the class DOM property of body in the onEnter function of UI-Router, ...), but is there a nice way to do that?

Or is it all about making the div[ui-view] full height (which is not trivial) and setting the background on this element to mimick how applying a background on the body takes up the full viewport?

like image 705
jack_kerouac Avatar asked Jul 21 '15 15:07

jack_kerouac


1 Answers

So to sum up my learnings, there are two ways to do it. Both require the $state service to be in the $rootScope. The elegance of this can be disputed, but I will go for this solution.

  1. If the background classes are depending on the state only, add them to the state's custom data:

Example code:

.state({
    ...,
    data: {
        bodyClass: 'bg1'
    }
});

Then, on the body, put an ng-class and reference the current state's data:

<body ng-class="$state.current.data.bodyClass">
  1. If the background classes are (besides the state) depending on something else (like a state parameter or a service, ...), use the state's resolve mechanism:

Example code:

.state({
    ...,
    resolve: {
        bodyClass: function($stateParams) {
            // do some calculation
            return ...
        }
    }
});

Then, on the body, put an ng-class and reference the resolved class name through $state.$current.locals.globals:

<body ng-class="$state.$current.locals.globals.bodyClass">

In both cases, bodyClass can anything that is valid for the ng-class directive.

like image 179
jack_kerouac Avatar answered Oct 02 '22 16:10

jack_kerouac