AngularJS установка CSS-файла из API с использованием JS

0

В настоящее время у меня есть API, который возвращает URL-адрес файла CSS, который я хотел бы включить в мой весь сайт. Поступайте с этим изменением url, я не могу жестко закодировать URL. В настоящее время я работаю над "view1", но я хочу, чтобы он работал над всем сайтом. (поэтому попробуйте реализовать его в index.html). Я не уверен, что лучший способ сделать это, и я уверен, что мой подход неправильный. Любое понимание было бы полезно или решение моей проблемы.

Мое приложение отформатировано под патроны.

app/                    --> all of the source files for the application
  app.css               --> default stylesheet
  components/           --> all app specific modules
    API/                  --> Mock Slim API for testing
      index.php             --> Root for the API
  view1/                --> the view1 view template and logic
    view1.html            --> the partial template
    view1.js              --> the controller logic
    view1_test.js         --> tests of the controller
  view2/                --> the view2 view template and logic
    view2.html            --> the partial template
    view2.js              --> the controller logic
    view2_test.js         --> tests of the controller
  app.js                --> main application module
  index.html            --> app layout file (the main html template file of the app)

Вот View1, который в настоящее время работает

JS

'use strict';

angular.module('myApp.view1', ['ngRoute'])

.config(['$routeProvider', function($routeProvider) {
  $routeProvider.when('/view1', {
    templateUrl: 'view1/view1.html',
    controller: 'View1Ctrl'
  });
}])

.controller('View1Ctrl', ['$scope', '$http', function($scope, $http) {
        $http.get('/api/auth/test').
          then(function(response) {
            $scope.css = response.data.temp.css;
          }, function(response) {
            alert('Error retrieving css: ' + response);
          });
}]);  

HTML

<head>
    <link ng-attr-href="{{css}}" rel="stylesheet" type="text/css">
</head>

Вот мои корневые файлы, которые не работают

JS

    'use strict';

// Declare app level module which depends on views, and components
angular.module('myApp', [
    'ngRoute',
    'myApp.authentication',
    'myApp.view1',
    'myApp.view2',
    'myApp.version'
]).
    config(['$routeProvider','$httpProvider','$locationProvider', function($routeProvider, $httpProvider, $locationProvider) {

        $httpProvider.interceptors.push('TokenInterceptor');

        // intercept API 401 responses and force authentication
        $httpProvider.interceptors.push(function ($q, $location, AuthenticationService) {
            //some code has been removed here
        });

        $routeProvider.otherwise({redirectTo: '/view1'});

    }])
    /*This is part of a test*/
    .controller('', ['$scope', '$http', function($scope, $http) {
        $http.get('/api/auth/test').
            then(function(response) {
                $scope.css = response.data.temp.css;
            }, function(response) {
                alert('Error retrieving css: ' + response);
            });
    }]);
    /*This is part of a test*/

HTML

<head>
    <link ng-attr-href="{{css}}" rel="stylesheet" type="text/css">
</head>

Вопрос 1: Есть ли лучший способ сделать это? <-this - это то, что я хочу

Вопрос 2: Если нет, почему это не работает? <- согласится на

Мои догадки в том, что HTML работает до JS, и когда JS запускается, чтобы изменить {{css}} на правильный ответ, слишком поздно, чтобы включить его. Но если это так, то почему это работает на View1, а не на корневом индексе?

  • 0
    Вы привязали свой контроллер к своему представлению, используя ng-controller ? В вашем случае вы должны рассмотреть возможность его привязки к <html> или <head>
  • 0
    почему вы не можете включить его без ajax? Также вероятно, что ваш <head> находится вне области действия контроллера. Директива была бы лучше
Показать ещё 2 комментария

3 ответа

0
Лучший ответ

Позвольте мне сначала ответить на ваш вопрос 2.

Когда угловые бутстрапы сначала пересекают узлы DOM, затем просматривают все соответствующие директивы, оценивают их, компилируют и, наконец, связывают их. Причина, по которой ваш второй фрагмент кода не работает, заключается в том, что ваш {{css}} не имеет ничего общего, поскольку он не имеет надлежащей scope привязки.

Что вы можете сделать, это на самом деле объявить ng-controller на уровне <head>, и пусть этот контроллер выполнит свою работу. Что-то вроде этого:

.controller('cssCtrl',['$scope','$http', function($scope,$http){
 $http.get('/api/auth/test').
        then(function(response) {
            $scope.css = response.data.temp.css;
        }, function(response) {
            alert('Error retrieving css: ' + response);
        });
 }]

И в вашем html:

<head ng-controller="cssCtrl">
  <link ng-attr-href="{{css}}" rel="stylesheet" type="text/css">
</head>

Вот пример plnkr, который демонстрирует, как это сделать.

ng-controller пригодится здесь, так как вам действительно не нужно определять route для него сам по себе. Обратите внимание, что ваш css не будет загружен, пока ваши угловые бутстрапы не cssCtrl и ваш cssCtrl будет cssCtrl. Будет какая-то задержка в этом, и, следовательно, наш первый вопрос, есть ли у нас лучший способ сделать это?

Я бы сказал, если у вас есть условная логика представления, основанная на самом угловом приложении, то используйте ng-if и ng-class. Если вам нужны более низкие уровни, используйте ng-style.

Если вы действительно загружаете всю новую таблицу стилей CSS на основе определенной конфигурации/настроек, я бы сказал, пусть сервер (бэкэнд) справится с этим. Сервер определит, какой тип css должен быть загружен на основе конфигурации (возможно, разные региональные приложения имеют разные стили css) и создаст свой сайт. Вашему внешнему приложению (угловому) просто нужно будет слушать сервер и загружать, не переваривая его.

Конечно, это не на 100% лучший способ. Если вам действительно нужен CSS-код, основанный на интерфейсе, то пойдите для него и создайте приложение таким образом! Только вы хорошо знаете этот пример использования приложения. Возможно, вы можете обернуть весь SPA в MainCtrl и MainView, и пусть каждая конфигурация разрешится сначала до манипуляции с DOM.

0

Какие серверные технологии вы используете? Я думаю, что было бы намного проще и менее проблематично извлекать файл CSS со стороны сервера и выводить его в статический файл CSS, который вы просто включаете на свою страницу index.html. Сначала будет выполняться код на стороне сервера, а ваш код на стороне клиента вообще не должен касаться этого.

Вы также можете проверить наличие файла и получить только новую копию, если текущая версия старше определенного времени.

0

Вам по-прежнему необходимо предоставить дополнительную информацию.

  • вы используете ui-router или обычную угловую маршрутизацию?
  • как ваш url структурирован, что наследует от чего?

Если его маршрутизатор ui упрощает работу. Все, что вам нужно сделать, это получить CSS в контроллере родителя, из которого выведены другие URL-адреса. Обычно я стараюсь, чтобы все мои страницы наследовались от одного родителя, который обычно является пустой страницей.

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

  • 0
    Я обновил вопрос, чтобы отобразить больше файлов JS.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню