DEV Community

Oke Vese
Oke Vese

Posted on

How I Styled AngularJS Components by Routes

In an old side project, an application that suggests meals based on calorie input, with AngularJS for the frontend I had been using the ng-style directive to set the CSS styles in the template.

The controller looked like this:


(function() {
  angular
    .module('foodApp')
    .controller('calorieCtrl', calorieCtrl);

  function calorieCtrl() {
    var vm = this;

    vm.styleCalorieInput = {
      "background-color": "#3cb9c6",      
      "border-color": "transparent",      
      "border-radius": "10px"
    };

    vm.styleError = {
      "color": "#f3c4a3"
    };
    ...
}();

Here I am using the controllerAs syntax to create a view model I can bind my data to so I can access it in the template like so:

...
<div class="well" ng-style="vm.styleCalorieInput">
  <span ng-style="vm.styleError">...</span>
</div>
...

Even though this approach works I didn't like that I was setting the styles in the component, I wanted to define a separate stylesheet for each component like I can with Angular and still define stylesheets for the entire application in a single file if I wanted to.

I found angular-route-styles that allows me to declare route-specific styles using the $routeProvider service and it solves my problem perfectly.

I used it by copying route-styles.js into my lib folder and included the file in index.html like so:


<!DOCTYPE html>
<html ng-app="foodApp">
...
  <body ng-view>
    <script src="/lib/route-styles.js"></script>
    ...
  </body>
</html>

Now we need to add routeStyles as a module dependency to app.js and add the css property and value (where to find the css file(s)) to the when route definition.

(function() {
  // Adds `routeStyles` along with `ngRoute` dependency
  angular.module('foodApp', ['ngRoute', 'routeStyles']);

  function config($routeProvider) {
    $routeProvider
      .when('', {
        templateUrl: '/calorie/calorie.view.html',
        controller: 'calorieCtrl',
        controllerAs: 'vm',
        css: '/calorie/calorie.css'
      })
      .otherwise({ redirectTo: '/' });
  }

   angular
    .module('foodApp')
    .config(['$routeProvider', config]);

})();

Now I could delete all the style data bindings from the controller and the ng-style directives from the view. The controller now looks like this with the deleted part commented out:

// calorie/calorie.js

(function() {
  angular
    .module('foodApp')
    .controller('calorieCtrl', calorieCtrl);

  function calorieCtrl() {
    var vm = this;

    /**
    vm.styleCalorieInput = {
      "background-color": "#3cb9c6",      
      "border-color": "transparent",      
      "border-radius": "10px"
    };

    vm.styleError = {
      "color": "#f3c4a3"
    }; 
    */
    ...
}();

And in the view, I changed the ng-style directives to classes with similar names (there are better ways to do this):

...
<div class="well styleCalorieInput">
  <span class="styleError">...</span>
</div>
...

And moved the CSS properties to a newly created calorie.css file in the same folder:

.styleCalorieInput {
  background-color: #3cb9c6;
  border-color: transparent;
  border-radius: 10px;
}

styleError {
   color: #f3c4a3;
}

If you're curious, you can read more about how Tennisgent implemented his solution here on StackOverflow.

Top comments (0)