What is the proper/accepted way to use separate stylesheets for the various views my application uses?
Currently I'm placing a link element in the view/partial's html at the top but I've been told this is bad practice even though all modern browsers support it but I can see why it's frowned upon.
The other possibility is placing the separate stylesheets in my index.html's head
but I would like it to only load the stylesheet if its view is being loaded in the name of performance.
Is this bad practice since styling won't take effect until after the css is loaded form the server, leading to a quick flash of unformatted content in a slow browser? I have yet to witness this although I'm testing it locally.
Is there a way to load the CSS through the object passed to Angular's $routeProvider.when
?
Thanks in advance!
'use strict'; angular.module('app') .run( [ '$rootScope', '$state', '$stateParams', function($rootScope, $state, $stateParams) { $rootScope.$state = $state; $rootScope.$stateParams = $stateParams; } ] ) .config( [ '$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
@tennisgent's solution is great. However, I think is a little limited.
Modularity and Encapsulation in Angular goes beyond routes. Based on the way the web is moving towards component-based development, it is important to apply this in directives as well.
As you already know, in Angular we can include templates (structure) and controllers (behavior) in pages and components. AngularCSS enables the last missing piece: attaching stylesheets (presentation).
For a full solution I suggest using AngularCSS.
ng-app
in the<html>
tag. This is important when you have multiple apps running on the same pagehttps://github.com/door3/angular-css
Here are some examples:
Routes
Directives
Additionally, you can use the
$css
service for edge cases:You can read more about AngularCSS here:
http://door3.com/insights/introducing-angularcss-css-demand-angularjs
@sz3, funny enough today I had to do exactly what you were trying to achieve: 'load a specific CSS file only when a user access' a specific page. So I used the solution above.
But I am here to answer your last question: 'where exactly should I put the code. Any ideas?'
You were right including the code into the resolve, but you need to change a bit the format.
Take a look at the code below:
I've just tested and it's working fine, it injects the html and it loads my 'home.css' only when I hit the '/home' route.
Full explanation can be found here, but basically resolve: should get an object in the format
You can name the 'key' anything you like - in my case I called 'style'.
Then for the value you have two options:
If it's a string, then it is an alias for a service.
If it's function, then it is injected and the return value is treated as the dependency.
The main point here is that the code inside the function is going to be executed before before the controller is instantiated and the $routeChangeSuccess event is fired.
Hope that helps.
Awesome, thank you!! Just had to make a few adjustments to get it working with ui-router:
If you only need your CSS to be applied to one specific view, I'm using this handy snippet inside my controller:
This will add a class to my
body
tag when the state loads, and remove it when the state is destroyed (i.e. someone changes pages). This solves my related problem of only needing CSS to be applied to one state in my application.I know this question is old now, but after doing a ton of research on various solutions to this problem, I think I may have come up with a better solution.
In case anyone in the future is interested, here's what I came up with:
1. Create a custom directive for the
<head>
element:This directive does the following things:
$compile
) an html string that creates a set of<link />
tags for every item in thescope.routeStyles
object usingng-repeat
andng-href
.<link />
elements to the<head>
tag.$rootScope
to listen for'$routeChangeStart'
events. For every'$routeChangeStart'
event, it grabs the "current"$$route
object (the route that the user is about to leave) and removes its partial-specific css file(s) from the<head>
tag. It also grabs the "next"$$route
object (the route that the user is about to go to) and adds any of its partial-specific css file(s) to the<head>
tag.ng-repeat
part of the compiled<link />
tag handles all of the adding and removing of the page-specific stylesheets based on what gets added to or removed from thescope.routeStyles
object.Note: this requires that your
ng-app
attribute is on the<html>
element, not on<body>
or anything inside of<html>
.2. Specify which stylesheets belong to which routes using the
$routeProvider
:This config adds a custom
css
property to the object that is used to setup each page's route. That object gets passed to each'$routeChangeStart'
event as.$$route
. So when listening to the'$routeChangeStart'
event, we can grab thecss
property that we specified and append/remove those<link />
tags as needed. Note that specifying acss
property on the route is completely optional, as it was omitted from the'/some/route/2'
example. If the route doesn't have acss
property, the<head>
directive will simply do nothing for that route. Note also that you can even have multiple page-specific stylesheets per route, as in the'/some/route/3'
example above, where thecss
property is an array of relative paths to the stylesheets needed for that route.3. You're done Those two things setup everything that was needed and it does it, in my opinion, with the cleanest code possible.
Hope that helps someone else who might be struggling with this issue as much as I was.