Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS : dynamic stylesheet link tag fires request too soon

I'm facing an issue similar (but not identical, please bear with me) to the one described in Conditionally-rendering css in html head

I'm also "lazily" loading a stylesheet, getting the filename from a scope variable that I initialize at the very beginning of my controllers :

<link rel="stylesheet" data-ng-href="css/{{ filename }}.css" />

As I'm using ng-href (here in its data- form), I'm indeed avoiding unwanted requests such as :

http://localhost/css/%7B%7B%20filename%7D%7D.css

But it all still fires too soon, and I'm getting this almost every time :

http://localhost/css/.css

Which seems to mean the request fires between the moment when Angular removes its own markup and the moment it replaces it with the correct value (which it does, a moment later, and then my stylesheet loads properly). I reckon it's not even possible...!?

I figured I might be providing a value for the filename scope variable too late, but as I said, it's the first thing done in my controller :

angular.module('myControllers', [])
    .controller('TestCtrl', ['$scope', function($scope) {
        $scope.filename = 'test';

        // some more code...
    }]);

I'm using Angular 1.1.5 ; is there anything I can do about it ? It's not that big of a deal, but it would still be better if I could fix it.

EDIT : Here comes the complete code, as requested. I won't include page templates as they are irrelevant regarding the issue.

index.html :

<!DOCTYPE html>
<html lang="en" data-ng-app="myapp">

<head>
    <meta charset="utf-8" />
    <title>My App</title>
    <link rel="stylesheet" data-ng-href="/assets/css/{{ filename }}.css" />
</head>

<body>
    <div id="app" class="app" style="display: none;" data-ng-view></div>

    <script src="/assets/js/lib/angular/angular.min.js"></script>
    <script src="/assets/js/app/app.js"></script>
    <script src="/assets/js/app/controllers.js"></script>
</body>

</html>

app.js :

var app = angular.module('myapp', ['myControllers'])
    .config(['$locationProvider', '$routeProvider', function($locationProvider, $routeProvider) {
        $locationProvider.hashPrefix('!');
        $routeProvider

        .when('/', {
            templateUrl: 'path/to/my/template.html',
            controller: 'TestCtrl'
        })

        .otherwise({ redirectTo: '/' });
    }]);

app.run();

controllers.js :

angular.module('myControllers', [])
    .controller('TestCtrl', ['$scope', '$rootScope', function($scope, $rootScope) {
        $rootScope.filename = 'stylesheet';
    }]);

(Yes, I tried with an empty controller just like this one, same issue.)

like image 725
neemzy Avatar asked Aug 29 '13 14:08

neemzy


People also ask

What is $timeout in AngularJS?

The '$timeout' service of AngularJS is functionally similar to the 'window. setTimeout' object of vanilla JavaScript. This service allows the developer to set some time delay before the execution of the function.

What is ngInit?

The ngInit directive allows you to evaluate an expression in the current scope. This directive can be abused to add unnecessary amounts of logic into your templates. There are only a few appropriate uses of ngInit : aliasing special properties of ngRepeat , as seen in the demo below.

What is not recommended in AngularJS?

It is tempting to do too much work in the AngularJS controller. After all, the controller is where the view first has access to JavaScript via $scope functions. However, doing this will cause you to miss out on code sharing across the site and is not recommended by AngularJS documentation.

What does ng cloak do?

The ng-cloak directive prevents the document from showing unfinished AngularJS code while AngularJS is being loaded. AngularJS applications can make HTML documents flicker when the application is being loaded, showing the AngularJS code for a second, before all code are executed.


1 Answers

I solved it by adding an ngIf directive to the link tag, so it's not rendered until filename isn't falsy. Kinda dirty I know, but it actually works !

<link rel="stylesheet" data-ng-if="filename" data-ng-href="css/{{ filename }}.css" />
like image 131
neemzy Avatar answered Oct 26 '22 17:10

neemzy