Как добавить таблицу стилей в <head> в AngularJS $routeProvider?

Я хочу загрузить определенный файл CSS только тогда, когда пользователь обращается к представлению contact.html на моем приложении/сайте AngularJS. Я нашел этот ответ, который почти имел смысл для меня Как включить просмотр/частичный конкретный стиль в AngularJS Принятый ответ charlietfl гласит:

Может быть добавлена ​​новая таблица стилей, которая будет находиться в пределах $routeProvider. Для простота использования строки, но также может создать новый элемент ссылки, или создать службу для таблиц стилей

/* check if already exists first - note ID used on link element*/
/* could also track within scope object*/
if( !angular.element('link#myViewName').length){
    angular.element('head').append('<link id="myViewName" href="myViewName.css" rel="stylesheet">');
}

Самое большое преимущество prelaoding на странице - любые фоновые изображения будут уже существует, и меньше lieklyhood of FOUC

Проблема в том, что я не знаю точно, где в моем $routeProvider добавить код. charlietfl упоминает, куда помещать его в комментарий, который читает

нет, если когда маршрут не был вызван. Может помещать этот код в контрольный вызов контроллера, когда в пределах маршрутаProvider, или, возможно, в пределах ответного вызова разрешения, который скорее всего срабатывает раньше

Я изменил свой $routeProvider по рекомендации. Я добавил resolve в объект, следующий за .when('/contact'. Вот мой код

angular.module('maxmythicApp', ['ngResponsiveImages'])
  .config(function ($locationProvider, $routeProvider) {
    $locationProvider.html5Mode(true);
    $locationProvider.hashPrefix = '!';
    $routeProvider
      .when('/', {
        templateUrl: '/views/design.html',
        controller: 'MainCtrl'
      })
      .when('/design', {
        templateUrl: '/views/design.html',
        controller: 'MainCtrl'
      })
      .when('/about', {
        templateUrl: '/views/about.html',
        controller: 'MainCtrl'
      })
      .when('/contact', {
        templateUrl: '/views/contact.html',
        controller: 'MainCtrl',
        resolve: 
          if( !angular.element('link#myViewName').length){
            angular.element('head').append('<link id="myViewName" href="myViewName.css" rel="stylesheet">');
          }
      })
      .otherwise({
        redirectTo: '/'
      });
  });

Будет ли это работать?

Ответ 1

Я сделал для него сервис.

Важная часть кода:

var head = angular.element(document.querySelector('head')); // TO make the code IE < 8 compatible, include jQuery in your page and replace "angular.element(document.querySelector('head'))" by "angular.element('head')"

if(head.scope().injectedStylesheets === undefined)
{
    head.scope().injectedStylesheets = [];
    head.append($compile("<link data-ng-repeat='stylesheet in injectedStylesheets' data-ng-href='{{stylesheet.href}}' rel='stylesheet' />")(scope)); // Found here : http://stackoverflow.com/a/11913182/1662766
}

head.scope().injectedStylesheets.push({href: "/url/to/style.css"});

Полный код в Github: https://github.com/Yappli/angular-css-injector)

Ответ 2

ОБНОВЛЕНО: Вот решение для инъекции (загрузки) определенного CSS с помощью $routeProvider.

Решение, описанное ниже, является альтернативой применению разных классов и заголовков страниц на основе маршрута, который может использоваться в других ситуациях.

Для каждого маршрута я создал новый ключ под названием " bodyClass" и " title" (но вы могли бы называть все, что вам нравится), и это выглядит так:

'use strict';
var myApp = angular.module('myApp', 'ngResource'])
.config(function ($routeProvider) {

myApp.siteName = 'My Cool App';

$routeProvider
    .when('/home', {
     title:'Home - ' + myApp.siteName,
     bodyClass: 'home',
     templateUrl: 'views/home.html',
     controler: 'bmsHomeCtrl'
    })
    .when('/contact', {
      title:'Contact - ' + myApp.siteName,
      bodyClass: 'contact',
      templateUrl: 'views/contact.html',
      controler: 'bmsContactCtrl'
    })
    .otherwise({
      redirectTo: '/home'
    });
});

Затем для каждого события $routeChangeSuccess я изменяю <title> страницы, а также класс <body>.

myApp.run(['$location', '$rootScope', function($location, $rootScope) {
    $rootScope.$on('$routeChangeSuccess', function (event, current, previous) {

      if (current.$$route) {

        $rootScope.title = current.$$route.title;

        $rootScope.bodyClass = current.$$route.bodyClass;
      }
    });
}]);

Вы помещаете код выше в тот же самый основной файл app.js (например).

На моей странице index.html, которая отображает представления, у меня есть следующие коды, чтобы выбрать заголовок и класс:

<title>{{ title }}</title>

<body class="{{ bodyClass }}">

Итак, если я нахожу домашнюю страницу своего приложения, тег title будет

<tittle> Home - My Cool App</tittle>

и тег body будет

<body class="home">

Он работает как шарм.

Я знаю, что это решение не загружает файл CSS, но вы можете поместить эти стили внутри класса .contact, который применяется, только когда вы нажмете конкретный маршрут.

Не уверен, решает ли ваша проблема, но я надеюсь, что это поможет или, по крайней мере, направить вас в правильном направлении.

Ответ 3

Для полного решения я предлагаю использовать AngularCSS.

Как вы уже знаете, в Angular мы можем включать шаблоны (структуру) и контроллеры (поведение) на страницах и компонентах. AngularCSS позволяет использовать последний недостающий элемент: прикреплять таблицы стилей (презентацию).

Пример маршрутов:

$routeProvider
.when('/page1', {
  templateUrl: 'page1/page1.html',
  controller: 'page1Ctrl',
  /* Now you can bind css to routes */
  css: 'page1/page1.css'
})
.when('/page2', {
  templateUrl: 'page2/page2.html',
  controller: 'page2Ctrl',
  /* You can also enable features like bust cache, persist and preload */
  css: {
    href: 'page2/page2.css',
    bustCache: true
  }
})
.when('/page3', {
  templateUrl: 'page3/page3.html',
  controller: 'page3Ctrl',
  /* This is how you can include multiple stylesheets */
  css: ['page3/page3.css','page3/page3-2.css']
})
.when('/page4', {
  templateUrl: 'page4/page4.html',
  controller: 'page4Ctrl',
  css: [
    {
      href: 'page4/page4.css',
      persist: true
    }, {
      href: 'page4/page4.mobile.css',
      /* Media Query support via window.matchMedia API
       * This will only add the stylesheet if the breakpoint matches */
      media: 'screen and (max-width : 768px)'
    }, {
      href: 'page4/page4.print.css',
      media: 'print'
    }
  ]
});

Пример директивы:

myApp.directive('myDirective', function () {
  return {
    restrict: 'E',
    templateUrl: 'my-directive/my-directive.html',
    css: 'my-directive/my-directive.css'
  }
});

Подробнее об AngularCSS здесь:

http://door3.com/insights/introducing-angularcss-css-demand-angularjs

Ответ 4

Я думаю, что лучший/самый простой ответ - это тот, который я оставил здесь. Кто-то другой задал один и тот же вопрос, поэтому я придумал простой код и небольшой репозиторий github, чтобы справиться с этим сценарием.