Conditionally-rendering css in html head

扶醉桌前 提交于 2019-11-27 21:17:16
Artem Andreev

You should use ng-href instead of href.

<link ng-repeat="stylesheet in stylesheets" ng-href="{{stylesheet.href}}" type="{{stylesheet.type}}" rel="stylesheet" />

Example

I made a AngularJS service to use easily the @Artem solution.

It's here on GitHub.

There's a another option using $route.resolve and promises. This will wait until the CSS is actually loaded not only added to the head (after that the browser just starts retrieving the file and depending on CSS size can cause page reflow).

// Routing setup
.config(function ($routeProvider) {
  $routeProvider
  .when('/home', {
      controller: 'homeCtrl', 
      templateUrl: 'home.tpl.html'
  }).when('/users', {
      controller: 'usersCtrl', 
      controllerAs: 'vm',
      templateUrl: 'users.tpl.html',
      resolve: {
        load: ['injectCSS', function (injectCSS) {
          return injectCSS.set("users", "users.css");
        }]
      }
  }).otherwise({
      // default page
      redirectTo: '/home'
  });
})

Service implementation

.factory("injectCSS", ['$q', '$http', 'MeasurementsService', function($q, $http, MeasurementsService){
  var injectCSS = {};

  var createLink = function(id, url) {
    var link = document.createElement('link');
    link.id = id;
    link.rel = "stylesheet";
    link.type = "text/css";
    link.href = url;
    return link;
  }

  var checkLoaded = function (url, deferred, tries) {
    for (var i in document.styleSheets) {
      var href = document.styleSheets[i].href || "";
      if (href.split("/").slice(-1).join() === url) {
        deferred.resolve();
        return;
      }
    }
    tries++;
    setTimeout(function(){checkLoaded(url, deferred, tries);}, 50); 
  };

  injectCSS.set = function(id, url){
    var tries = 0,
      deferred = $q.defer(),
      link;

    if(!angular.element('link#' + id).length) {
      link = createLink(id, url);
      link.onload = deferred.resolve;
      angular.element('head').append(link);
    }
    checkLoaded(url, deferred, tries);

    return deferred.promise;
  };

  return injectCSS;
}])

You could add a timeout using tries if this is something you would like to include.

Check out this post for more details:https://medium.com/angularjs-meetup-south-london/angular-dynamically-injecting-css-file-using-route-resolve-and-promises-7bfcb8ccd05b

I've created a very simple example of how make a conditionaly css addition

<link rel="stylesheet" ng-if="lang_direction == 'rtl'" ng-href="{{lang_direction == 'rtl' ? 'css/rtl.css' : ''}}" >

For anyone wishing to create truly dynamic CSS at runtime with AngularJS this is what I used.

index.html

<head> <style type="text/css" ng-bind-html="styles"></style> </head>

cssService

this.$rootScope.myStyles = ".test { color : red; }";

This is just an example, it may be better for you to put the styles into an indexController if you have one and keep it off the $rootScope

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!