Buduję dyrektywę kątową, która będzie używana w kilku różnych miejscach. Nie zawsze mogę zagwarantować strukturę plików aplikacji, w której jest używana dyrektywa, ale mogę zmusić użytkownika do umieszczenia directive.js
i directive.html
(nie rzeczywistych nazw plików) w tym samym folderze.
Kiedy strona ocenia element directive.js
, uważa, że templateUrl
jest względem siebie. Czy można ustawić, templateUrl
aby był względny w stosunku do directive.js
pliku?
Lub jest zalecane, aby po prostu uwzględnić szablon w samej dyrektywie.
Myślę, że mógłbym chcieć załadować różne szablony na podstawie różnych okoliczności, więc wolałbym móc użyć ścieżki względnej zamiast aktualizować directive.js
javascript
angularjs
path
pedalpete
źródło
źródło
Odpowiedzi:
Aktualnie wykonywany plik skryptu zawsze będzie ostatnim w tablicy scripts, więc możesz łatwo znaleźć jego ścieżkę:
// 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') }; });
Jeśli nie masz pewności, jaka jest nazwa skryptu (na przykład, jeśli pakujesz wiele skryptów w jeden), użyj tego:
return { templateUrl: currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1) + 'directive.html' };
Uwaga : W przypadkach, w których używane jest zamknięcie, kod powinien znajdować się na zewnątrz, aby zapewnić, że bieżący skrypt jest oceniany we właściwym czasie, na przykład:
// 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; })() );
źródło
<script>
tag, natychmiast go wykonuje przed kontynuowaniem renderowania strony, więc w globalnym zakresie skryptu ostatni<script>
tag jest zawsze ostatnim.path = currentScriptPath.split("/"); path.pop(); path.push("directive.html");
to nie miało żadnych zależności od nazw plików i obsługuje „dyrektywa.js”, „/directive.js” i „ścieżka / do / dyrektywy.js”. Konkurs code-golf polega na połączeniu ich w jedną instrukcję (używając splice i in.).Jak powiedziałeś, że chciałeś dostarczyć różne szablony w różnym czasie do dyrektyw, dlaczego nie pozwolić, aby sam szablon był przekazywany do dyrektywy jako atrybut?
<div my-directive my-template="template"></div>
Następnie użyj czegoś takiego jak
$compile(template)(scope)
wewnątrz dyrektywy.źródło
$compile
metodę, która ma zostać przekazana? Może i$compile
tak będę musiał użyć , więc może to być dobra sugestia.Oprócz odpowiedzi Alona Gubkina sugerowałbym zdefiniowanie stałej za pomocą wyrażenia funkcji natychmiastowo wywoływanej do przechowywania ścieżki skryptu i wstrzyknięcia jej do dyrektywy:
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' } });
źródło
Ten kod znajduje się w pliku o nazwie route.js
Poniższe nie działają dla mnie:
var scripts = document.getElementsByTagName("script") var currentScriptPath = scripts[scripts.length-1].src; var baseUrl = currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1);
co następuje:
var bu2 = document.querySelector("script[src$='routes.js']"); currentScriptPath = bu2.src; baseUrl = currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1);
Mój test jest oparty na następującym blogu dotyczącym korzystania z narzędzia require to lazy load angular: http://ify.io/lazy-loading-in-angularjs/
require.js wywołuje bootstrap requireConfig
requireConfig tworzy angular app.js
angular app.js tworzy moje route.js
Miałem ten sam kod obsługiwany przez Revel Web Framework i mvc asp.net. W revel document.getElementsByTagName ("skrypt") utworzono ścieżkę do mojego wymaganego pliku js bootstrap, a NIE do moich routs.js. w ASP.NET MVC utworzył ścieżkę do elementu skryptu Link przeglądarki wstrzykniętego do programu Visual Studio, który jest umieszczany tam podczas sesji debugowania.
to jest mój kod pracy 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' ] } } }; });
To jest mój wynik konsoli podczas uruchamiania z 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/
Kolejną fajną rzeczą, którą zrobiłem, jest skorzystanie z wymaganej konfiguracji i umieszczenie w niej niestandardowych konfiguracji. tj. dodaj
customConfig: { baseRouteUrl: '/AngularLazyBaseLine/Home/Content' }
możesz go następnie uzyskać, używając następującego kodu z wnętrza Routes.js
var requireConfig = requirejs.s.contexts._.config; console.log('requireConfig.customConfig.baseRouteUrl:' + requireConfig.customConfig.baseRouteUrl);
czasami trzeba z góry zdefiniować adres URL, czasami trzeba go dynamicznie wygenerować. Twój wybór dla Twojej sytuacji.
źródło
Niektórzy mogą zasugerować, że jest to trochę "hakerskie", ale myślę, że dopóki nie będzie tylko jednego sposobu na zrobienie tego, wszystko będzie hackem.
Miałem dużo szczęścia, robiąc to również:
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; } });
Następnie podczas używania kodu w aplikacji po dołączeniu modułu do aplikacji.
W funkcji konfiguracji aplikacji:
.config(['$routeProvider', '$appUrlProvider', function ($routeProvider, $appUrlProvider) { $routeProvider .when('/path:folder_path*', { controller: 'BrowseFolderCntrl', templateUrl: $appUrlProvider.route('views/browse-folder.html') }); }]);
Oraz w kontrolerze aplikacji (jeśli jest to wymagane):
var MyCntrl = function ($scope, $appUrl) { $scope.templateUrl = $appUrl('views/my-angular-view.html'); };
Tworzy nowy błąd javascript i pobiera ślad stosu. Następnie analizuje wszystkie adresy URL (z wyłączeniem numeru linii / znaku wywołującego).
Możesz wtedy po prostu wyciągnąć pierwszy z tablicy, który będzie bieżącym plikiem, w którym działa kod.
Jest to również przydatne, jeśli chcesz scentralizować kod, a następnie wyciągnąć drugą (
[1]
) z tablicy, aby uzyskać lokalizację pliku wywołującegoźródło
Jak zauważyło kilku użytkowników, odpowiednie ścieżki nie są pomocne podczas budowania plików statycznych i bardzo polecam to zrobić.
W Angular jest sprytna funkcja o nazwie $ templateCache , która w mniejszym lub większym stopniu buforuje pliki szablonów, a następnym razem, gdy angular będzie tego wymagał, zamiast wysyłać rzeczywiste żądanie, udostępnia wersję buforowaną. Oto typowy sposób korzystania z niego:
module = angular.module('myModule'); module.run(['$templateCache', function($templateCache) { $templateCache.put('as/specified/in/templateurl/file.html', '<div>blabla</div>'); }]); })();
W ten sposób zarówno rozwiązujesz problem względnych adresów URL, jak i zyskujesz na wydajności.
Oczywiście podoba nam się pomysł posiadania osobnych plików html z szablonami (w przeciwieństwie do reagowania), więc samo powyższe nie jest dobre. Oto system kompilacji, który może czytać wszystkie pliki html szablonów i konstruować js, taki jak powyższy.
Istnieje kilka modułów html2js dla grunt, gulp, webpack i to jest ich główna idea. Osobiście często używam gulp, więc szczególnie lubię gulp-ng-html2js, ponieważ robi to bardzo łatwo.
źródło