├── .gitignore ├── .travis.yml ├── Gruntfile.js ├── LICENSE ├── README.md ├── bower.json ├── karma.conf.js ├── package.json ├── test └── ui-router-styles.js └── ui-router-styles.js /.gitignore: -------------------------------------------------------------------------------- 1 | bower_components 2 | node_modules 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '0.10' 4 | before_script: 5 | - 'npm install -g bower grunt-cli' 6 | - 'npm install' 7 | - 'bower install' 8 | notifications: 9 | email: 10 | - origin.of@gmail.com 11 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | grunt.initConfig({ 3 | karma: { 4 | travis: { 5 | configFile: 'karma.conf.js', 6 | singleRun: true, 7 | browsers: ['PhantomJS'] 8 | } 9 | } 10 | }); 11 | 12 | grunt.loadNpmTasks('grunt-karma'); 13 | grunt.registerTask('test', ['karma:travis']) 14 | }; 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Manuel Mazzuola 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | angular-ui-router-styles 2 | ==================== 3 | 4 | [](https://travis-ci.org/manuelmazzuola/angular-ui-router-styles) 5 | 6 | This is a simple module for AngularJS that provides the ability to have route-specific CSS stylesheets, by integrating with Angular [uiRouter](https://github.com/angular-ui/ui-router). 7 | 8 | What does it do? 9 | --------------- 10 | 11 | It allows you to declare partial-specific or route-specific styles for your app using 12 | Angular's ui-router `$stateProvider` service. This solves that problem by allowing you to do something like this: 13 | 14 | ```javascript 15 | app.config(['$stateProvider', function($stateProvider){ 16 | $stateProvider 17 | 18 | .state('state1', { 19 | url: '/state1', 20 | controller: 'State1controller', 21 | template: '
', 22 | data: { 23 | css: [ 24 | 'styles/custom-state1.css', 25 | { 26 | name: 'layout', 27 | href: 'styles/state1-layout.css' 28 | } 29 | ] 30 | } 31 | }) 32 | 33 | .state('state1.state12', { 34 | url: '/:id', 35 | controller: 'State12Controller', 36 | templateUrl: 'views/my-template.html', 37 | data: { 38 | css: [ 39 | 'styles/custom-state1.state12.css', 40 | { 41 | name: 'layout', 42 | href: 'styles/state1.state12-layout.css' 43 | } 44 | ] 45 | } 46 | }) 47 | 48 | .state('state2', { 49 | url: '/state2', 50 | controller: 'State2Controller', 51 | templateUrl: 'views/another-template.html', 52 | data: { 53 | css: ['styles/custom-state2.css', 'styles/another.css'] 54 | } 55 | }) 56 | 57 | .state('state3', { 58 | url: '/state3', 59 | controller: 'State3Controller', 60 | templateUrl: 'views/another-super-template.html', 61 | data: { 62 | css: 'styles/custom-state3.css' 63 | } 64 | }) 65 | // more states can be declared here 66 | }]); 67 | ``` 68 | 69 | * For state1 state we will have CSS: ['styles/custom-state1.css', 'styles/state1-layout.css']. 70 | * For state1.state2 state we will have CSS: ['styles/custom-state1.css', 'styles/custom-state1.state12.css', 'styles/state1.state12-layout.css']. 71 | * For state2 state we will have CSS: ['styles/custom-state2.css', 'styles/another.css']. 72 | * For state3 state we will have CSS: ['styles/custom-state3.css']. 73 | 74 | 75 | How to install: 76 | --------------- 77 | 78 | * Install it with Bower via `bower install angular-ui-router-styles --save` 79 | 80 | * Ensure that your application module specifies `uiRouterStyles` as a dependency: `angular.module('myApplication', ['uiRouterStyles'])` 81 | 82 | * Add the directive `ui-router-styles` to your body tag or wherever you want 83 | ``` 84 | 85 | 86 | 87 | 88 | 89 | ``` 90 | 91 | * Add css file(s) relative path to the state data object 92 | ```javascript 93 | .state('state1', { 94 | url: '/state', 95 | controller: 'StateCtrl', 96 | templateUrl: 'views/my-template.html', 97 | data: { 98 | css: 'styles/some-overrides.css' 99 | } 100 | }) 101 | ``` 102 | 103 | A simple plunkr to understand the usage: http://plnkr.co/edit/HIcYEj2QRqBCwbZCU0Il?p=preview 104 | 105 | **Things to notice:** 106 | * Specifying a css property on the route is completely optional. If the state doesn't have a css property, the service will simply do nothing for that route. 107 | * You can even have multiple page-specific stylesheets per state, where the css property is an **array** of relative paths or objects contains the name and href attributes. 108 | * If a parent state exists the data object is inherited. 109 | 110 | 111 | This directive does the following things: 112 | 113 | * It compiles (using `$compile`) an html string that creates a set of tags for every item in the `data.css` state property using `ng-repeat` and `ng-href`. 114 | * It appends that compiled set of `` elements to the `` tag. 115 | * It then uses the `$rootScope` to listen for `'$stateChangeSuccess'` events. For every `'$stateChangeSuccess'` event, it cleans all css appended before and adds the new css file(s) to the `` tag if there are any. 116 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-ui-router-styles", 3 | "version": "1.1.1", 4 | "main": "ui-router-styles.js", 5 | "dependencies": { 6 | "angular": ">=1.4.9", 7 | "angular-ui-router": "^0.2.13" 8 | }, 9 | "devDependencies": { 10 | "angular-mocks": "~1.4.9" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | module.exports = function(config) { 2 | config.set({ 3 | plugins: [ 4 | 'karma-jasmine', 5 | 'karma-phantomjs-launcher' 6 | ], 7 | 8 | // base path, that will be used to resolve files and exclude 9 | basePath: '', 10 | 11 | // testing framework to use (jasmine/mocha/qunit/...) 12 | frameworks: ['jasmine'], 13 | 14 | // list of files / patterns to load in the browser 15 | files: [ 16 | 'bower_components/angular/angular.js', 17 | 'bower_components/angular-mocks/angular-mocks.js', 18 | 'bower_components/angular-ui-router/release/angular-ui-router.js', 19 | 'ui-router-styles.js', 20 | 'test/ui-router-styles.js' 21 | ], 22 | browsers: ['PhantomJS'], 23 | singleRun: true 24 | }); 25 | }; 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-ui-router-styles", 3 | "main": "ui-router-styles.js", 4 | "version": "1.1.1", 5 | "private": false, 6 | "scripts": { 7 | "test": "grunt test" 8 | }, 9 | "devDependencies": { 10 | "grunt": "^0.4.5", 11 | "grunt-karma": "^0.12.1", 12 | "jasmine-core": "^2.4.1", 13 | "karma": "^0.13.19", 14 | "karma-jasmine": "^0.3.7", 15 | "karma-phantomjs-launcher": "^0.2.3", 16 | "phantomjs": "^1.9.19" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/ui-router-styles.js: -------------------------------------------------------------------------------- 1 | // test/ui-router-styles.js 2 | 'use strict'; 3 | 4 | describe('Unit: should inject some css', function () { 5 | var $c, $scope, green = 'green', red = 'red', $state; 6 | 7 | // load the directive 8 | beforeEach(module('ui.router', function($locationProvider) { 9 | $locationProvider.html5Mode(false); 10 | })); 11 | 12 | beforeEach(module('uiRouterStyles')); 13 | beforeEach(module(defineStates)); 14 | beforeEach(inject(function(_$compile_, _$rootScope_, _$state_) { 15 | $c = _$compile_; 16 | $state = _$state_; 17 | $scope = _$rootScope_.$new(); 18 | } 19 | )); 20 | 21 | function initStateTo(state) { 22 | $state.go(state); 23 | $scope.$apply(); 24 | expect($state.current.name).toBe(state); 25 | } 26 | 27 | it("should inject the green css", function() { 28 | var element; 29 | element = $c('