Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing body background color with angularjs

I want to be able to change the background color of <body> depending on what the current path is.

I tried doing it by checking $location.path() whenever the path was changed and then using the ng-style directive to change the background color but this seems like a hack (and didn't work).

What would be a more decoupled way to achieve this?

Here's the code I wrote if anyone wants to see it.

app.controller('backgroundCtrl', ['$rootScope', '$scope', '$route', '$location', function($rootScope, $scope, $route, $location){
  $rootScope.$on('$routeChangeStart', function(){

    if ($location.path() == '/'){
      $scope.backgroundStyle = {background: '#ffffff'};
    } else {
      $scope.backgroundStyle = {background: '#000000'};
    }

  });
}]);
like image 758
user1215653 Avatar asked Mar 26 '14 09:03

user1215653


People also ask

How to change background color in AngularJS?

<body ng-app=""> <input type="button" value="set color" ng-click="myStyle={color:'red'}"> <input type="button" value="set background" ng-click="myStyle={'background-color':'brown'}"> <input type="button" value="clear" ng-click="myStyle={}">

How to use ngstyle in AngularJS?

AngularJS ng-style DirectiveThe ng-style directive specifies the style attribute for the HTML element. The value of the ng-style attribute must be an object, or an expression returning an object. The object consists of CSS properties and values, in key value pairs.

How do you color the background in HTML?

How to Add Background Color in HTML. To add background color in HTML, use the CSS background-color property. Set it to the color name or code you want and place it inside a style attribute. Then add this style attribute to an HTML element, like a table, heading, div, or span tag.


2 Answers

To decouple such a dynamic change in style, data, content and etc., it is often practical to create another angular module that contains an interface(Custom Provider) that can give you access to these changes before and after the configuration level. Here is a plunker to provide a view of what I'll be discussing below.

For this answer, I have created a small module(route-data.js) with a provider, RouteData, which exposes two function configurations:

applyConfig() - assigns settings to be accessed in the RouteData service. hookToRootScope() - hooks the RouteData service in the $rootScope hence making it available to all child scopes to be created and the entire application.

The RouteData provider has a RouteData() service that provides access to methods which sets and gets RouteData settings that will be provided in the $routeProvider configuration.

(If you're not familiar with providers and services, read more about it here)

(If you're not familiar with the config() and run() methods, you can read more in here)

route-data.js

angular.module('RouteData', []).

provider('RouteData', function () {
  var settings = {};
  var hookToRootScope = false;

  this.applyConfig = function(newSettings) {
    settings = newSettings;
  };

  this.hookToRootScope = function(enableRootScopeHook) {
    hookToRootScope = enableRootScopeHook;
  };

  function RouteData() {

    this.set = function(index, value) {
      settings[index] = value;
    };

    this.get = function(index) {
      if(settings.hasOwnProperty(index)) {
        return settings[index];
      } else {
        console.log('RouteData: Attempt to access a propery that has not been set');
      }
    };

    this.isHookedToRootSope = function() {
      return hookToRootScope;
    };
  }

  this.$get = function() {
      return new RouteData();
  };
}).

run(['$location', '$rootScope', 'RouteData', function($location, $rootScope, RouteData) {
  if(RouteData.isHookedToRootSope()) {
    $rootScope.RouteData = RouteData;
  }

  $rootScope.$on('$routeChangeStart', function(event, current, previous) {
    var route = current.$$route;
    if(typeof(route) !== 'undefined' && typeof(route['RouteData']) !== 'undefined') {
      var data = route['RouteData'];
      for(var index in data)
        RouteData.set(index, data[index]);
    } 
  });
}]);

The script below shows how to use the RouteData Module above via injecting the RouteDataProvider in the configuration level and apply default configurations such as the bodyStyle via RouteDataProvider.applyConfig(), you may also add more settings before the application is fully running. Hook it up in the $rootScope by setting RouteDataProvider.hookToRootScope() to true. Lastly, appending data, RouteData e.g.

RouteData: {
      bodyStyle: {
        'background-color': 'green'
      }
    }

to be sent in by the $routeProvider and processed by the run() method defined in the RouteData module which initializes the settings for the RouteData services to be accessed in the application.

script.js

angular.module('app', ['ngRoute', 'RouteData']).

config(['$routeProvider', 'RouteDataProvider', function($routeProvider, RouteDataProvider) {
  RouteDataProvider.applyConfig({
    bodyStyle: {
      'background-color': 'white'
    }
  });

  RouteDataProvider.hookToRootScope(true);

  $routeProvider.when('/landing', {
    RouteData: {
      bodyStyle: {
        'background-color': 'green'
      }
    },
    templateUrl: 'landing.html',
    controller: 'LandingController'  
  }).when('/login', {
    RouteData: {
     bodyStyle: {
         'background-color': 'gray',
         padding: '10px',
         border: '5px solid black',
         'border-radius': '1px solid black'
     }
    },
    templateUrl: 'login.html',
    controller: 'LoginController'
  }).otherwise({
    redirectTo: '/landing'
  });

}]).

controller('LoginController', ['$scope', function($scope) {

}]).

controller('LandingController', ['$scope', function($scope) {

}]);

So the final piece of code to be added in your index page or any other page would be something like this.

A portion of index.html

<body ng-style="RouteData.get('bodyStyle')"> 
    <a href="#/landing">Landing</a> | 
    <a href="#/login">Login</a>
    <div ng-view></div>
</body>
like image 69
ryeballar Avatar answered Oct 20 '22 04:10

ryeballar


One way to style the body is to add ng-view as a body attribute, then use ng-class or ng-style (I did not use any other option to date).

For example:

<!doctype html>
<html ng-app="my-app">
  <head>
    <title>My Site</title>
    <script src="angular/angular.js"></script>
  </head>
  <body ng-class="{login:loginBody}" ng-view>
    <script src="my-app.js"></script>
  </body>
</html>

In this example, the login class is applied to the body only when loginBody is a true value in the current scope, set in a login controller.

This is much less flexible than the approach offered by @ryeballar. It may just be enough in some cases.

like image 4
Eric Platon Avatar answered Oct 20 '22 05:10

Eric Platon