Угловая директива templateUrl относительно файла .js
Я создаю угловую директиву, которая будет использоваться в нескольких разных местах. Я не всегда могу гарантировать файловую структуру приложения, в котором используется директива, но я могу заставить пользователя поместить directive.js
и directive.html
(а не настоящие имена файлов) в одну и ту же папку.
Когда страница оценивает directive.js
, она считает, что templateUrl
относительна к себе. Можно ли установить templateUrl
относительно файла directive.js
?
Или рекомендуется просто включить шаблон в свою директиву.
- Относительные пути изображений в JavaScript
- Создание большого треугольника с верхним указателем из существующего кода с помощью SVG
- В Node.js, как я могу определить путь к этому модулю?
- Как сгладить отработанный путь SVG?
- Почему некоторые профессиональные веб-дизайнеры используют абсолютные пути вместо относительных путей (например, для CSS, Javascript, изображений и т. Д.)?
Я думаю, что я могу захотеть загрузить разные шаблоны на основе разных обстоятельств, поэтому предпочтет использовать относительный путь, а не обновлять directive.js
- Рисовать текст в d3 arc javascript
- Доступ к вложенным объектам JavaScript со строковым ключом
- Получение только имени файла из пути с помощью Javascript
- JS D3 textPath не отображается
- Как создать / инициализировать файловый объект, используя путь к файлу html5
- Преобразование пути многоугольника Google Maps к пути SVG
- Незакрытый путь SVG закрыт
- Получить путь загрузки браузера с помощью javascript
Текущий исполняемый файл сценария всегда будет последним в массиве скриптов, поэтому вы можете легко найти его путь:
// directive.js var scripts = document.getElementsByTagName("script") var currentScriptPath = scripts[scripts.length-1].src; angular.module('app', []) .directive('test', function () { return { templateUrl: currentScriptPath.replace('directive.js', 'directive.html') }; });
Если вы не знаете, что такое имя скрипта (например, если вы упаковываете несколько скриптов в один), используйте это:
return { templateUrl: currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1) + 'directive.html' };
Примечание . В случаях, когда используется закрытие, ваш код должен быть снаружи, чтобы гарантировать, что текущий сценарий оценивается в правильное время, например:
// directive.js (function(currentScriptPath){ angular.module('app', []) .directive('test', function () { return { templateUrl: currentScriptPath.replace('directive.js', 'directive.html') }; }); })( (function () { var scripts = document.getElementsByTagName("script"); var currentScriptPath = scripts[scripts.length - 1].src; return currentScriptPath; })() );
Как вы сказали, вы хотели бы предоставить разные шаблоны в разное время для директив, почему бы не позволить самому шаблону передавать директиву в качестве атрибута?
<div my-directive my-template="template"></div>
Затем используйте что-то вроде $compile(template)(scope)
внутри директивы.
Этот код находится в файле, называемом routes.js
Для меня не работало:
var scripts = document.getElementsByTagName("script") var currentScriptPath = scripts[scripts.length-1].src; var baseUrl = currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1);
Следующее:
var bu2 = document.querySelector("script[src$='routes.js']"); currentScriptPath = bu2.src; baseUrl = currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1);
Мой тест основан на следующем блоге об использовании, требующем ленивой нагрузки угловой: http://ify.io/lazy-loading-in-angularjs/
Require.js порождает загрузку requireConfig
RequireConfig порождает угловые app.js
Angular app.js порождает мои маршруты.js
У меня был тот же код, который обслуживался веб-картой revel и asp.net mvc. В revel document.getElementsByTagName («script») был создан путь к моему файлу bootstrap js и NOT my routes.js. В ASP.NET MVC он создал путь к встраиваемому скрипту Visual Studio, который был добавлен во время сеансов отладки.
Это мой рабочий route.js код:
define([], function() { var scripts = document.getElementsByTagName("script"); var currentScriptPath = scripts[scripts.length-1].src; console.log("currentScriptPath:"+currentScriptPath); var baseUrl = currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1); console.log("baseUrl:"+baseUrl); var bu2 = document.querySelector("script[src$='routes.js']"); currentScriptPath = bu2.src; console.log("bu2:"+bu2); console.log("src:"+bu2.src); baseUrl = currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1); console.log("baseUrl:"+baseUrl); return { defaultRoutePath: '/', routes: { '/': { templateUrl: baseUrl + 'views/home.html', dependencies: [ 'controllers/HomeViewController', 'directives/app-style' ] }, '/about/:person': { templateUrl: baseUrl + 'views/about.html', dependencies: [ 'controllers/AboutViewController', 'directives/app-color' ] }, '/contact': { templateUrl: baseUrl + 'views/contact.html', dependencies: [ 'controllers/ContactViewController', 'directives/app-color', 'directives/app-style' ] } } }; });
вdefine([], function() { var scripts = document.getElementsByTagName("script"); var currentScriptPath = scripts[scripts.length-1].src; console.log("currentScriptPath:"+currentScriptPath); var baseUrl = currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1); console.log("baseUrl:"+baseUrl); var bu2 = document.querySelector("script[src$='routes.js']"); currentScriptPath = bu2.src; console.log("bu2:"+bu2); console.log("src:"+bu2.src); baseUrl = currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1); console.log("baseUrl:"+baseUrl); return { defaultRoutePath: '/', routes: { '/': { templateUrl: baseUrl + 'views/home.html', dependencies: [ 'controllers/HomeViewController', 'directives/app-style' ] }, '/about/:person': { templateUrl: baseUrl + 'views/about.html', dependencies: [ 'controllers/AboutViewController', 'directives/app-color' ] }, '/contact': { templateUrl: baseUrl + 'views/contact.html', dependencies: [ 'controllers/ContactViewController', 'directives/app-color', 'directives/app-style' ] } } }; });
вdefine([], function() { var scripts = document.getElementsByTagName("script"); var currentScriptPath = scripts[scripts.length-1].src; console.log("currentScriptPath:"+currentScriptPath); var baseUrl = currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1); console.log("baseUrl:"+baseUrl); var bu2 = document.querySelector("script[src$='routes.js']"); currentScriptPath = bu2.src; console.log("bu2:"+bu2); console.log("src:"+bu2.src); baseUrl = currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1); console.log("baseUrl:"+baseUrl); return { defaultRoutePath: '/', routes: { '/': { templateUrl: baseUrl + 'views/home.html', dependencies: [ 'controllers/HomeViewController', 'directives/app-style' ] }, '/about/:person': { templateUrl: baseUrl + 'views/about.html', dependencies: [ 'controllers/AboutViewController', 'directives/app-color' ] }, '/contact': { templateUrl: baseUrl + 'views/contact.html', dependencies: [ 'controllers/ContactViewController', 'directives/app-color', 'directives/app-style' ] } } }; });
Это мой консольный вывод при работе с Revel.
currentScriptPath:http://localhost:9000/public/ngApps/1/requireBootstrap.js routes.js:8 baseUrl:http://localhost:9000/public/ngApps/1/ routes.js:10 bu2:[object HTMLScriptElement] routes.js:13 src:http://localhost:9000/public/ngApps/1/routes.js routes.js:14 baseUrl:http://localhost:9000/public/ngApps/1/
Еще одна приятная вещь, которую я сделал, это воспользоваться конфигурацией require и вставить в нее некоторые пользовательские конфигурации. Т.е. добавить
customConfig: { baseRouteUrl: '/AngularLazyBaseLine/Home/Content' }
Вы можете получить его, используя следующий код изнутри routes.js
var requireConfig = requirejs.s.contexts._.config; console.log('requireConfig.customConfig.baseRouteUrl:' + requireConfig.customConfig.baseRouteUrl);
Иногда вам необходимо определить базовый уровень, иногда вам нужно динамически генерировать его. Ваш выбор для вашей ситуации.
В дополнение к ответу от Алона Губкина я бы предложил определить константу, используя выражение «Вызванное мгновенное выражение», чтобы сохранить путь к скрипту и ввести его в директиву:
angular.module('app', []) .constant('SCRIPT_URL', (function () { var scripts = document.getElementsByTagName("script"); var scriptPath = scripts[scripts.length - 1].src; return scriptPath.substring(0, scriptPath.lastIndexOf('/') + 1) })()) .directive('test', function(SCRIPT_URL) { return { restrict : 'A', templateUrl : SCRIPT_URL + 'directive.html' } });
Некоторые могут предложить немного «взломать», но я думаю, пока есть только один способ сделать это, все будет хаки.
Мне тоже повезло:
angular.module('ui.bootstrap', []) .provider('$appUrl', function(){ this.route = function(url){ var stack = new Error('dummy').stack.match(new RegExp(/(http(s)*\:\/\/)[^\:]+/igm)); var app_path = stack[1]; app_path = app_path.slice(0, app_path.lastIndexOf('App/') + 'App/'.length); return app_path + url; } this.$get = function(){ return this.route; } });
Затем при использовании кода в приложении после включения модуля в приложение.
В функции конфигурации приложения:
.config(['$routeProvider', '$appUrlProvider', function ($routeProvider, $appUrlProvider) { $routeProvider .when('/path:folder_path*', { controller: 'BrowseFolderCntrl', templateUrl: $appUrlProvider.route('views/browse-folder.html') }); }]);
И в контроллере приложения (если требуется):
var MyCntrl = function ($scope, $appUrl) { $scope.templateUrl = $appUrl('views/my-angular-view.html'); };
Он создает новую ошибку javascript и вытаскивает трассировку стека. Затем он анализирует все URL-адреса (за исключением номера вызывающей линии / символа).
Затем вы можете просто вытащить первое в массиве, которое будет текущим файлом, в котором работает код.
Это также полезно, если вы хотите централизовать код, а затем вытащите второй ( [1]
) в массиве, чтобы получить местоположение вызывающего файла
Как указали некоторые пользователи, соответствующие пути не помогают при создании статических файлов, и я бы очень рекомендовал это сделать.
В Angular называется отличная функция $ templateCache , которая в большей или меньшей степени кэширует файлы шаблонов, и в следующий раз, когда этот угловой требует одного, вместо того, чтобы делать фактический запрос, он предоставляет кешированную версию. Это типичный способ его использования:
module = angular.module('myModule'); module.run(['$templateCache', function($templateCache) { $templateCache.put('as/specified/in/templateurl/file.html', '<div>blabla</div>'); }]); })();
Таким образом, вы оба решаете проблему относительных URL-адресов и получаете прибыль.
Конечно, нам нравится идея иметь отдельные шаблонные html-файлы (в отличие от реагирования), поэтому само по себе это нехорошо. Здесь идет система сборки, которая может читать все HTML-файлы шаблона и строить js, такие как выше.
Существует несколько модулей html2js для grunt, gulp, webpack, и это основная идея, стоящая за ними. Я лично использую gulp много, поэтому я особенно причудливый gulp-ng-html2js, потому что он делает именно это очень легко.