Угловая директива templateUrl относительно файла .js

Я создаю угловую директиву, которая будет использоваться в нескольких разных местах. Я не всегда могу гарантировать файловую структуру приложения, в котором используется директива, но я могу заставить пользователя поместить directive.js и directive.html (а не настоящие имена файлов) в одну и ту же папку.

Когда страница оценивает directive.js , она считает, что templateUrl относительна к себе. Можно ли установить templateUrl относительно файла directive.js ?

Или рекомендуется просто включить шаблон в свою директиву.

Я думаю, что я могу захотеть загрузить разные шаблоны на основе разных обстоятельств, поэтому предпочтет использовать относительный путь, а не обновлять directive.js

Текущий исполняемый файл сценария всегда будет последним в массиве скриптов, поэтому вы можете легко найти его путь:

 // 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, потому что он делает именно это очень легко.

  • Преобразование относительного пути в абсолютный с помощью JavaScript
  • Что означает «./» (точечная косая черта) в терминах расположения пути к файлу HTML?
  • Относительные пути в Javascript во внешнем файле
  • Как отобразить круг SVG с использованием start и endAngle
  • Давайте будем гением компьютера.