Jonathan.
Jonathan.

Reputation: 55604

CSS in an angular directive

I'm writing an Angular directive to display some information about a music album, currently it shows the information below the album art, but if the element gets too small then it should shrink the album art and put the information next to it. At the moment I just have the html in the page directly and have css to do the changes in the main page, but this causes the page to be quite monolithic as it also display other things, which is why I want to seperate it out into directives.

However I can't see how to include CSS in the directive, I don't want to include it inline in the html, and I could put a style tag in the html and put it in there, but then it would be repeated every time I use the directive. Is there some way of injecting a link to a CSS file into the head from the directive? Like there is a templateUrl field is there a stylesheetUrl or something?

Upvotes: 4

Views: 567

Answers (3)

Ed_
Ed_

Reputation: 19138

Structuring an angular app is one of the hardest things about learning angular. Angular tries hard to modularise code, but (the current state of) html, css, and javascript doesn't really allow you to package the things together, so you have to find a way that works well for you.

The way I keep things separate (yet together) is generally using my build system (I use gulp), and a CSS preprocessor (for me, Stylus).

My process for creating a new directive is as follows:

  1. Define a new angular module (in its own file) my-albums.coffee:

    angular.module('my-albums', [])
    
    .directive('myAlbumDirective', ()->
      restrict: 'A'
      templateUrl: 'SomeTemplate.jade'
      # etc.
    )
    
  2. Create a jade template my-album-directive.jade

    .album
      img(ng-src="{{album.imageUrl}})
      span.name {{album.name}}
    
  3. Create the stylus file with the same name as the module prefixed with an underscore: _my-albums.styl. In here I will include module specific css.

    [myAlbumDirective]
      .album
        display flex
        flex-direction column
        @media screen and (min-width: 600px)
          flex-direction row
    

Then, whenever I import an angular module into my app.coffee (which contains a long list of module imports), I also import its style in my main.styl stylesheet:

@import '../my-albums/_my-albums.styl'

When I run my build system, it (among other things):

  • Automatically compiles .jade files into a app.templates angular module (pre-populating the $templateCache (app.templates is included in the imports in app.coffee
  • Compiles and concatenates all coffeescript into script.js
  • Compiles and concatenates all stylus files whose filenames do not begin with an underscore into style.css

Then inside my index page I just have two imports:

script(src='js/app.js')
link(rel='stylesheet', href='css/style.css')

TL;DR:

There's no easy way of keeping your directive code separate from the rest of the page, but if you research build systems and other people's angular project structures, you'll find something you like.

Note SoonTM things will be neater (see web components and angular 2.0)

Upvotes: 0

s.alem
s.alem

Reputation: 13079

You can inject css in your directive like this:

var head = document.getElementsByTagName('head')[0];
var cs = document.createElement('link');
cs.rel = 'stylesheet';
cs.href = 'css/myStylesheet.css';
head.appendChild(cs);

So a directive would look like this:

app.directive('myDirective', function () {
    var head = document.getElementsByTagName('head')[0];
    var cs = document.createElement('link');
    cs.rel = 'stylesheet';
    cs.href = 'css/myStylesheet.css';
    head.appendChild(cs);
    return {
        templateUrl:'templates/myTemplate.html',
        link: function (scope, elm, attrs, ctrl) {

        }
    };
});

Upvotes: 0

MarcoS
MarcoS

Reputation: 17721

You could check this module: angular-css-injector.
Be warned it's currently only compatible with angular 1.2.x...

Upvotes: 1

Related Questions