Angular 绑定后相对 templateUrls 的 $templateCache 404 错误
Angular $templateCache 404 error for relative templateUrls after bundling
我正在使用带有 AngularJS 配置文件的 Grails 3 以及 Angular Toastr plugin。
当我 运行 处于开发模式的应用程序时,一切正常,但是当我捆绑应用程序(没有缩小)时,无法再加载插件中的模板,并且出现以下错误:
Error: [$compile:tpload] Failed to load template: directives/toast/toast.html (HTTP status: 404 Not Found)
我检查了捆绑代码并找到了以下行:
angular.module('toastr')
.constant('toastrConfig', {
allowHtml: false,
autoDismiss: false,
closeButton: false,
closeHtml: '<button>×</button>',
containerId: 'toast-container',
extendedTimeOut: 1000,
iconClasses: {
error: 'toast-error',
info: 'toast-info',
success: 'toast-success',
warning: 'toast-warning'
},
maxOpened: 0,
messageClass: 'toast-message',
newestOnTop: true,
onHidden: null,
onShown: null,
onTap: null,
positionClass: 'toast-top-right',
preventDuplicates: false,
preventOpenDuplicates: false,
progressBar: false,
tapToDismiss: true,
target: 'body',
templates: {
toast: 'directives/toast/toast.html',
progressbar: 'directives/progressbar/progressbar.html'
},
timeOut: 5000,
titleClass: 'toast-title',
toastClass: 'toast'
});
和
angular.module("toastr").run(["$templateCache", function($templateCache) {$templateCache.put("directives/progressbar/progressbar.html","<div class=\"toast-progress\"></div>\n");
$templateCache.put("directives/toast/toast.html","<div class=\"{{toastClass}} {{toastType}}\" ng-click=\"tapToast()\">\n <div ng-switch on=\"allowHtml\">\n <div ng-switch-default ng-if=\"title\" class=\"{{titleClass}}\" aria-label=\"{{title}}\">{{title}}</div>\n <div ng-switch-default class=\"{{messageClass}}\" aria-label=\"{{message}}\">{{message}}</div>\n <div ng-switch-when=\"true\" ng-if=\"title\" class=\"{{titleClass}}\" ng-bind-html=\"title\"></div>\n <div ng-switch-when=\"true\" class=\"{{messageClass}}\" ng-bind-html=\"message\"></div>\n </div>\n <progress-bar ng-if=\"progressBar\"></progress-bar>\n</div>\n");}]);
看来模板缓存中的模板已正确初始化。
我尝试在控制器中注入 $templateCache 并调用 $templateCache.get("directives/toast/toast.html")
并且这个 returns 我是正确的模板。
尽管我可以使用 $templateCache.get(...)
访问模板,但捆绑时模板未正确加载的原因可能是什么?
关于 $templateCache 的正确用法,我是否遗漏了什么?
PS:我注意到 angular-bootstrap 模板存在同样的问题
编辑 我发现,当我使用绝对 templateUrls 时一切正常,显然,我不完全理解相对 templateUrls 是如何工作的。
当应用程序被捆绑时,所有的 JS 代码都被连接到一个具有不同路径的文件中,这似乎中断了通过 $templateCache 的加载。现在,将所有 templateUrls 设为绝对是一个解决方案,但我无法在不更改代码的情况下对使用相对 templateUrl 的插件执行此操作。
所以,有人可以向我解释这里实际发生了什么,以及我如何在不触及插件代码的情况下解决这个问题吗?
我发现,在为 Angular 生成 Grails 应用程序时,它会自动在 index.gsp 中包含以下行:
<script type="text/javascript">
window.contextPath = "${request.contextPath}";
</script>
这会设置 window.contextPath
当应用程序被捆绑用于生产时会破坏 Angular $templateCache。
换句话说:设置 window.contextPath = ""
否则 $templateCache 中的模板解析将失败。
我正在使用带有 AngularJS 配置文件的 Grails 3 以及 Angular Toastr plugin。
当我 运行 处于开发模式的应用程序时,一切正常,但是当我捆绑应用程序(没有缩小)时,无法再加载插件中的模板,并且出现以下错误:
Error: [$compile:tpload] Failed to load template: directives/toast/toast.html (HTTP status: 404 Not Found)
我检查了捆绑代码并找到了以下行:
angular.module('toastr')
.constant('toastrConfig', {
allowHtml: false,
autoDismiss: false,
closeButton: false,
closeHtml: '<button>×</button>',
containerId: 'toast-container',
extendedTimeOut: 1000,
iconClasses: {
error: 'toast-error',
info: 'toast-info',
success: 'toast-success',
warning: 'toast-warning'
},
maxOpened: 0,
messageClass: 'toast-message',
newestOnTop: true,
onHidden: null,
onShown: null,
onTap: null,
positionClass: 'toast-top-right',
preventDuplicates: false,
preventOpenDuplicates: false,
progressBar: false,
tapToDismiss: true,
target: 'body',
templates: {
toast: 'directives/toast/toast.html',
progressbar: 'directives/progressbar/progressbar.html'
},
timeOut: 5000,
titleClass: 'toast-title',
toastClass: 'toast'
});
和
angular.module("toastr").run(["$templateCache", function($templateCache) {$templateCache.put("directives/progressbar/progressbar.html","<div class=\"toast-progress\"></div>\n");
$templateCache.put("directives/toast/toast.html","<div class=\"{{toastClass}} {{toastType}}\" ng-click=\"tapToast()\">\n <div ng-switch on=\"allowHtml\">\n <div ng-switch-default ng-if=\"title\" class=\"{{titleClass}}\" aria-label=\"{{title}}\">{{title}}</div>\n <div ng-switch-default class=\"{{messageClass}}\" aria-label=\"{{message}}\">{{message}}</div>\n <div ng-switch-when=\"true\" ng-if=\"title\" class=\"{{titleClass}}\" ng-bind-html=\"title\"></div>\n <div ng-switch-when=\"true\" class=\"{{messageClass}}\" ng-bind-html=\"message\"></div>\n </div>\n <progress-bar ng-if=\"progressBar\"></progress-bar>\n</div>\n");}]);
看来模板缓存中的模板已正确初始化。
我尝试在控制器中注入 $templateCache 并调用 $templateCache.get("directives/toast/toast.html")
并且这个 returns 我是正确的模板。
尽管我可以使用 $templateCache.get(...)
访问模板,但捆绑时模板未正确加载的原因可能是什么?
关于 $templateCache 的正确用法,我是否遗漏了什么?
PS:我注意到 angular-bootstrap 模板存在同样的问题
编辑 我发现,当我使用绝对 templateUrls 时一切正常,显然,我不完全理解相对 templateUrls 是如何工作的。
当应用程序被捆绑时,所有的 JS 代码都被连接到一个具有不同路径的文件中,这似乎中断了通过 $templateCache 的加载。现在,将所有 templateUrls 设为绝对是一个解决方案,但我无法在不更改代码的情况下对使用相对 templateUrl 的插件执行此操作。
所以,有人可以向我解释这里实际发生了什么,以及我如何在不触及插件代码的情况下解决这个问题吗?
我发现,在为 Angular 生成 Grails 应用程序时,它会自动在 index.gsp 中包含以下行:
<script type="text/javascript">
window.contextPath = "${request.contextPath}";
</script>
这会设置 window.contextPath
当应用程序被捆绑用于生产时会破坏 Angular $templateCache。
换句话说:设置 window.contextPath = ""
否则 $templateCache 中的模板解析将失败。